I am trying to insert three fields into dictionary, so converted two fields into object type and added to the dictionary
int empId;
String empName;
decimal salary;
public EmployeeClass(string empName,decimal salary)
{
this.empName = empName;
this.salary = salary;
}
//creating dictionary object
Dictionary<int, object> employeeDictionary = new Dictionary<int, object>();
EmployeeClass emp;
for(int i=0;i<5;i++)
{
Console.WriteLine("Enter Employee " + (i+1) + " details ");
Console.WriteLine("Enter Employee ID ");
empId = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter Employee Name ");
empName = Console.ReadLine();
Console.WriteLine("Enter Salary of the employee ");
salary= Convert.ToDecimal(Console.ReadLine());
//creating object for two fields
emp= new EmployeeClass(empName,salary);
//adding to dictionary one is field and other object
employeeDictionary.Add(empId, emp);
}
Now I am trying to retrieve the details from the dictionary:
var list = employeeDictionary.Keys.ToList();
list.Sort();
Console.WriteLine("The Employee details according to EmpID is ");
foreach(var temp in list)
{
Console.WriteLine(temp + " " + employeeDictionary[temp].empName + " " + employeeDictionary[temp].salary);
}
but I am getting this error:
Object does not contain definition for empName and no extension method empName accepting a first argument of type Object
How to retrieve the details from dictionary when an object type is given?
1. Private vs public fields
Your first problem is that your properties (empName and salary) are private fields of EmployeeClass:
public class EmployeeClass
{
int empId;
String empName;
decimal salary;
...
}
You don't use an explicit access modifier, so per default your fields are private. Change it to this:
public class EmployeeClass
{
public int empId {get; private set;}
public String empName {get; private set;}
public decimal salary {get; private set;}
...
}
2. Use the correct type
Why are you using a Dictionary<int,object> if you want to store instances of EmployeeClass? Simply use a
Dictionary<int,EmployeeClass> employeeDirectory
So the compiler will know that the "object" in the dictionary is a EmployeeClass and will know it's properties. If you use object, the compiler has no way to know that there are those properties.
Related
I have to create an appropriate GUI to enter information for at least 10 employee. for each employee i have to enter the following information. employee ID, employee first name, employee last name and yearly salary. besides i have to check for the correctness of the input data. in addition i need to create a separate class EMPLOYEE, containing employee information: employee ID, first name , last name and yearly salary. the class should have constructors properties and methods. all the employee information has to be stored in a array of type employee. after reading form GUI the information about particular employee , also create an object of class employee(element of the array) with the relevant constructor. the user would like to be able to find the employee with lowest yearly salary despite of having more than one employee with lowest yearly salary. and display information about them. user should be provided with appropriate GUI to display the required information.
i need to assure including in my program appropriate code for handling exceptions and also methods where appropriate.
here is the class employee:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Project_employee
{
class Employee
{
private int employeeID;
private string fullName;
private string lastName;
private double salary;
public Employee()
{
employeeID = 0;
fullName = "";
lastName = "";
salary = 0.0;
}
public Employee(int empIDValue, string fullNameVal, string lastNameVal)
{
employeeID = empIDValue;
fullName = fullNameVal;
lastName = lastNameVal;
salary = 0.0;
}
public Employee(int empIDValue, string fullNameVal, string lastNameVal, double salaryValue)
{
employeeID = empIDValue;
fullName = fullNameVal;
lastName = lastNameVal;
salary = salaryValue;
}
public int EmployeeIDNum
{
get
{
return employeeID;
}
set
{
employeeID = value;
}
}
public string FullName
{
get
{
return fullName;
}
set
{
fullName = value;
}
}
public int Getinfo
{
get
{
return employeeID;
}
set
{
employeeID = value;
}
}
public string employeeInformationToString()
{
// employeeID = Convert.ToInt32(this.textBox1.Text);
return (Convert.ToString(employeeID) + " " + fullName + " " + lastName + " " + Convert.ToString(salary));
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project_employee
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
private void Searchbtn_Click(object sender, EventArgs e)
{
employee[0] = new Employee();
employee[1] = new Employee(17433, "Adrian", "Smith", 8000.00);
employee[2] = new Employee(17434, "Stephen", "Rad", 9000.00);
employee[3] = new Employee(17435, "Jesse", "Harris", 800.00);
employee[4] = new Employee(17436, "jonatan", "Morris", 9500.00);
employee[5] = new Employee(17437, "Morgen", "Freeman", 12000.00);
employee[6] = new Employee(17438, "Leory", "Gomez", 10200.00);
employee[7] = new Employee(17439, "Michael", "Brown", 9000.00);
employee[8] = new Employee(17440, "Andrew", "White", 3500.00);
employee[9] = new Employee(17441, "Maria", "Carson", 12000.00);
//employee[10] = new Employee(17442, "Mark", "Jonson", 17000.00);
for(int i = 0; i < 10; i++)
{
string employeeString = employee[i].employeeInformationToString() + "\r\n";
richTextBox1.AppendText(employeeString);
}
}
Employee[] employee = new Employee[10];
private void getinfibtn_Click(object sender, EventArgs e)
{
Find();
}
private void Find()
{
}
}
}
My question is:
How the user can find the employee with the lowest yearly salary. i have to make sure that there can be more than one employee with lowest yearly salary and display the information about them. providing the user with an appropriate GUI (e.g a message box) to display the required information with including appropriate code for handling exceptions and also use methods where appropriate?
You need to make your class Employee to implement the IComparable interface, then compare the objects against the salary and in the other class sort the array...
Example:
public class Employee :IComparable<Employee>
{
private int employeeID;
private string fullName;
private string lastName;
private double salary;
public int CompareTo(Employee other)
{
return salary.CompareTo(other.salary);
}
}
private void Find()
{
Array.Sort(employee); // after this Employee is sorted
employee[0];
or
employee[9];
}
this will give a list of lowest salary emplyees
employee.Add(new Employee(17434, "Stephen", "Rad", 9000.00));
employee.Add(new Employee(17435, "Jesse", "Harris", 800.00));
employee.Add(new Employee(17436, "jonatan", "Morris", 9500.00));
var c = employee.OrderBy(i => i.salary).ToList();
var e = employee.Where(i => Math.Abs(i.salary - c[0].salary) < 1).ToList();
Modified you code a little bit
class Employee
{
private int employeeID;
private string fullName;
private string lastName;
private double salary;
public double Salary
{
get
{
return salary;
}
set
{
salary = value;
}
}
//public Employee()
//{
// employeeID = 0;
// fullName = "";
// lastName = "";
// salary = 0.0;
//}
//public Employee(int empIDValue, string fullNameVal, string lastNameVal)
//{
// employeeID = empIDValue;
// fullName = fullNameVal;
// lastName = lastNameVal;
// salary = 0.0;
//}
public Employee(int empIDValue, string fullNameVal, string lastNameVal, double salaryValue)
{
employeeID = empIDValue;
fullName = fullNameVal;
lastName = lastNameVal;
salary = salaryValue;
}
public int EmployeeIDNum
{
get
{
return employeeID;
}
set
{
employeeID = value;
}
}
public string FullName
{
get
{
return fullName;
}
set
{
fullName = value;
}
}
public int Getinfo
{
get
{
return employeeID;
}
set
{
employeeID = value;
}
}
public string employeeInformationToString()
{
// employeeID = Convert.ToInt32(this.textBox1.Text);
return (Convert.ToString(employeeID) + " " + fullName + " " + lastName + " " + Convert.ToString(salary));
}
}
and to get min values in list
var minEmpSalarylist = employee.Where(x => x.Salary == employee.Min(y => y.Salary)).ToList();
If default constructor is present then all minEmpSalarylist become initialized with default constructor.
and
employee[0] = new Employee();
to change it to
employee[0] = new Employee(17433, "XXX", "YYY", 8000.00);
I've been going through the Spring Data Cassandra documentation (http://docs.spring.io/spring-data/cassandra/docs/1.0.1.RELEASE/reference/html/cassandra.core.html)
Basically, with proper annotation, I hoped the CassandraTemplate maps a row to a POJO object, but it didn't work as I expected.
For the call,
cassandraOps.queryForObject(s, Person.class)
I received an error as following:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to Person
Anything that I'm missing? Following is the same copy and paste from the doc above.
Person Class looks like:
#Table
public class Person {
#PrimaryKey
private String id;
private String name;
private int age;
public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
#Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
and the application class looks like...:
public class CassandraApp {
private static final Logger LOG = LoggerFactory.getLogger(CassandraApp.class);
private static Cluster cluster;
private static Session session;
public static void main(String[] args) {
try {
cluster = Cluster.builder().addContactPoints(InetAddress.getLocalHost()).build();
session = cluster.connect("mykeyspace");
CassandraOperations cassandraOps = new CassandraTemplate(session);
cassandraOps.insert(new Person("1234567890", "David", 40));
Select s = QueryBuilder.select().from("person");
s.where(QueryBuilder.eq("id", "1234567890"));
LOG.info(cassandraOps.queryForObject(s, Person.class).getId());
cassandraOps.truncate("person");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
CassandraTemplate's queryForObject(String,Class) is not meant for arbitrary object mapping. It is modeled after JdbcTemplate's queryForObject(String,Class) method. It's intended to take types that the Cassandra driver can convert directly.
To convert arbitrary application-defined classes, use queryForObject(String,RowMapper<T>) or one of its overloads. CqlTemplate doesn't know how to map arbitrary classes; you have to supply the RowMapper<T> implementation for your class T.
you can do it like this way:-
String myQuery = "select * from person where id=1234567890";
Person personObj = cassandraOperations.selectOne(myQuery, Person.class);
<<
For all
List<Person> personListObj = cassandraOperations.select(myQuery, Person.class); >>
this work for me using cassandraTemplete object perfectly... didn't try for cassandraOperation.
also you might need #Column(value = "your_columnName_in_DB") if your pojo class's variable name is different
like
#Column(value = "name")
private String userName;
#Column(value = "age")
private int userAge;
revert here if its work?
Also can you help me pass dynamic value to that myQuery string.. using object[] same like prepareStatment in SQL
thanks.
I am new to this concept of reflection and finding problem in retrieving property value from a string. E.g.
I have a class Employee with following properties :
public string Name {get;set;}
public int Age {get;set;}
public string EmployeeID {get;set;}
string s = "Name=ABCD;Age=25;EmployeeID=A12";
I want to retrieve the value of each property from this string and create a new object of Employee with those values retrieved from the string for each field.
Can anyone please suggest how it can be done using reflection ??
//may be..
string s = "Name=ABCD;Age=25;EmployeeID=A12";
string[] words = s.Split(';');
foreach (string word in words)
{
string[] data = word.Split('=');
string _data = data[1];
Console.WriteLine(Name);
}
Here an example of how you maybe could do it
it used Reflection like you wanted ^^
using System;
using System.Collections.Generic;
using System.Reflection;
namespace replace
{
public class Program
{
private static void Main(string[] args)
{
var s = "Name=ABCD;Age=25;EmployeeID=A12";
var list = s.Split(';');
var dic = new Dictionary<string, object>();
foreach (var item in list)
{
var probVal = item.Split('=');
dic.Add(probVal[0], probVal[1]);
}
var obj = new MyClass();
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
Console.WriteLine(dic[property.Name]);
if (property.PropertyType == typeof(Int32))
property.SetValue(obj, Convert.ToInt32(dic[property.Name]));
//else if (property.PropertyType== typeof(yourtype))
// property.SetValue(obj, (yourtype)dic[property.Name]);
else
property.SetValue(obj, dic[property.Name]);
}
Console.WriteLine("------------");
Console.WriteLine(obj.Name);
Console.WriteLine(obj.Age);
Console.WriteLine(obj.EmployeeID);
Console.Read();
}
}
public class MyClass
{
public string Name { get; set; }
public int Age { get; set; }
public string EmployeeID { get; set; }
}
}
//Data Model
[DynamoDBTable("ContactsTable")]
public class Contact
{
[DynamoDBHashKey(AttributeName = "Id")]
public string Id { get; set; }
[DynamoDBProperty(AttributeName = "FirstName")]
public string FirstName { get; set; }
[DynamoDBProperty(AttributeName = "LastName")]
public string LastName { get; set; }
[DynamoDBProperty(AttributeName = "Address1")]
public string Address1 { get; set; }
[DynamoDBProperty(AttributeName = "Address2")]
public string Address2 { get; set; }
}
public void SaveContactsToDynamoDb()
{
var config = new AmazonDynamoDBConfig();
config.ServiceURL = ConfigurationManager.AppSettings["ServiceURL"];
var context = new DynamoDBContext(new AmazonDynamoDBClient(config));
var contactBatchWrite = context.CreateBatchWrite<Contact>();
var contacts = GetContacts();
contactBatchWrite.AddPutItems(contacts.Select(contact => new Contact
{
Id = contact.Id.ToString(),
FirstName = contact.FirstName,
LastName = contact.LastName,
Address1 = contact.Address1,
Address2 = contact.Address2
}));
contactBatchWrite.Execute();
}
When I execute it it returns an exception saying that "AttributeValue may not contain an empty string". I understand that some of the fields for a particular contact that are being mapped might contain empty fields. As DynamoDB does not accept null or empty fields, is there any way that I can modify the data model to add some attribute to property which ignores if its null or empty? Or can anyone give me a better way to map/ handle in this situation. I do not want to add constant like "N/A" if null or empty.
Thank you.
DynamoDB does accept null as attribute value when mapping Objects. It just drops the attribute internally.
If you need 2 empty values (null and empty string) you will have to use an __EMPTY_STRING constant, otherwise - you can just use null.
class Student
{
private string FirstName { get; set; }
private string LastName { get; set; }
private int age { get; set; }
private int studentID { get; set; }
private static int count = 0;
**static Random randomNumber = new Random(); // works**
**Random randomNumber = new Random(); // doesn't work I get the same studentID number**
public Student()// constructor
{
this.studentID = randomNumber.Next(1000000, 100000000);
count++;
Console.WriteLine("count {0} studentID {1}", count, studentID);
}
public Student(string first, string last, int age)
{
this.studentID = randomNumber.Next(1000000, 100000000);
count++;
Console.WriteLine("count {0} studentID {1}", count, studentID);
this.FirstName = first;
this.LastName = last;
this.age = age;
}
...... continuation
a few get methods
...... continuation
public void PrintData()
{
Console.WriteLine("Name is {0}, Lastname is {1} , Age is {2} , studentID is {3}", FirstName, LastName, age, this.studentID);
}
Why do I keep getting the same number , but if I make the Random object static it generates/assigns new number. Not sure where my logic is faulty.
If you you keep creating new Random objects in the constructor it will reset the seed (If you don't supply arguments the seed is set to the current time (See: MSDN: Random constructor) - so if you create multiple Random objects very near each other (in time) then it will have the same seed). Since Random is not truely random (if you init it from the same seed you'll always get the same sequence back) you will get the same numbers back in the non-static version. The static version is created only once and you keep asking it for the next number in the sequence, hence it appears to give you actual random numbers.