I need to Create a Class and Property dynamically from database table (Employee).
I need to Create a class and property at runtime and assign value to property
for example
public class Employee
{
private int _Id;
public int Id
{
get { return _Id; }
set { _Id = value; }
}
private String _Code;
public String Code
{
get { return _Code; }
set { _Code = value; }
}
}
Then I need to access this class on object
List<Employee> objlstEmp = new List<Employee>();
Employee objEmp = new Employee();
objEmp.Id = 1;
objEmp.Code = "Emp01";
objlstEmp.Add(objEmp);
As others commented, from your example looks like you don't need to generate classes at runtime, but use an ORM framework and do that design time.
As it seems the topic is unfamiliar to you, I would recommend looking into Entity Framework and because you already have a DB, generate the model from that. Look up how to create the model from DB.
Related
What would be the easiest and least labour intensive (from the software POV) for me to be able to get a property (to be read and modified) from an entity generated via the Entity Framework?
Example (and simplified code) below:
// <auto-generated> from Entity Framework
public partial class tblCustomer
{
public int CustomerID { get; set; }
public string Status { get; set; }
}
For instance I would like:
tblCustomer customer = new tblCustomer();
int pCustomerID = customer.GetFieldByName("CustomerID");
pCustomerID = 100;
I've read a lot of answers about Reflection, but also comments that it's heavy processing (may be a bit excessive for my needs).
My example code may seem rather simplistic (so a solution would be rather pointless for that, the real code is based on large tables), but if there was some sort of GetFieldByName function I could reduce my code significantly as I have a lot of repetitious code doing the same stuff (just to different columns).
If I understand your problem correctly, I think you can use the changetracker for this (if the entity is in the context already).
dbContext.Entry(customer).CurrentValues["CustomerID"]
will give you the value of CustomerID for the customer object, provided it is attached to the dbContext instance.
If it is not part of the context, you can use Attach() to attach it first, or use Add(), if it's supposed to be a new record.
If you don't like to use Reflection the only way that i know is using a dictionary in your entities and also you can put all these stuff in a base class and your entities inherit it for example like that:
[Serializable]
public class BaseEntity
{
Dictionary<string, object> _dic;
public BaseEntity()
{
_dic = new Dictionary<string, object>();
}
public object this[string propertyName]
{
get
{
return _dic[propertyName];
}
set
{
_dic[propertyName] = value;
}
}
}
public class tblCustomer : BaseEntity
{
public int CustomerID
{
get
{
return (int)this["CustomerID"];
}
set
{
this["CustomerID"] = value;
}
}
public string Status
{
get
{
return (string)this["Status"];
}
set
{
this["Status"] = value;
}
}
}
tblCustomer customer = new tblCustomer();
int pCustomerID = customer["CustomerID"];
and about performance cost of Reflection you can for first time store your memberInfos in a static field and use it for all instances.
I have a model which contains the following property:
public Guid UniqueID
{
get { return Guid.NewGuid(); }
}
If I examine the object after it is created, I can see that a new guid is correctly created for the UniqueID field.
However, when I call db.SaveChanges(), I get an error back from Entity Framework stating that it cannot insert NULL into this field despite there being a value present.
Any ideas?
EDIT
private Guid _uniqueID = Guid.NewGuid();
public Guid UniqueID
{
get
{
if(_uniqueID == null){
_uniqueID = Guid.NewGuid();
}
return _uniqueID;
}
set
{
_uniqueID = value;
}
}
EF does not support get-only properties. There needs to be some way for EF to be able to set the value when loading form the database. You can use a private setter if you want to make the field immutable:
private Guid _uniqueID = Guid.NewGuid();
public Guid UniqueID
{
get
{
return _uniqueID;
}
private set
{
_uniqueID = value;
}
}
Note that this is slightly different from your edit. I have made the setter private and have taken out the if(_uniqueID == null) since a Guid is a value type and can never be null.
class example:
public class Customer
{
public int CustomerID { get; set; }
}
using the class:
Customer customer1 = new Customer();
customer1.CustomerID = 1;
Now how can I create a customer2 class with all the values that are stored in customer1?
You can do it manually:
var customer2 = new Customer { CustomerID = customer1.CustomerID };
You can implement ICloneable interface in Customer class:
public class Customer : ICloneable
{
private int CustomerID { get; set; }
public Customer Clone()
{
return new Customer { CustomerID = this.CustomerID };
}
object ICloneable.Clone()
{
return this.Clone();
}
}
and then use it:
var customer2 = customer1.Clone();
You can serialize your object into XML/JSON and then deserialize it into new object, as described in this answer: Deep cloning objects in C#.
Or you can use reflection to get and copy all properties/fields values into your new Customer instance. It could have bad performance, but you'd have to measure it to make sure how bad it is.
Edit
One more way to do that: you can make reflection version faster using Expression Tree! Get all fields/properties and compile all necessary assignments at runtime using Expression.Lambda. After that every next Clone call will use compiled code so there will be no performance drawback at all. I've created Clone<T> extension method which does exactly that, using Expression class, static constructor and reflection. You can find the code on CodePlex: CloneExtension.cs
Either you use reflection to copy the values or you would want deep clone (ICloneable).
To extend Marcin's answer, if all of your items in your class are value types or immutable types (int, double, string, ect.) you can just use MemberwiseClone(). This will create a shallow copy of the original object, and if all your members are immutable there is no need to do a deep copy. This can be useful if you have many objects in your class you need to copy over.
public sealed class Customer : ICloneable
{
private int CustomerID { get; set; }
public Customer Clone()
{
return (customer)this.MemberwiseClone();
}
object ICloneable.Clone()
{
return this.Clone();
}
}
What if you set the class up like so:
public class Customer
{
private Customer Parent {get; private set;}
private int _id;
public int CustomerID
{
get { return Parent == null ? _id : Parent.CustomerID; }
set
{
if(Parent != null)
throw new InvalidOperationException("...");
_id = value;
}
public Customer()
{
}
public static Customer Clone(Customer parent)
{
return new Customer{Parent = parent};
}
}
This would create a immutable clone. Now... if you need to be able to alter the values... then either take a different approach, or expand on it.
I have a class that has the following syntax:-
public class CorporateTeamTimeSheetTotalsForSpecifiedTimeFrame
{
private List<EmployeeMini> _EmployeesList = new List<EmployeeMini>();
private List<HolidayCalendar> _Holidays = new List<HolidayCalendar>();
public List<EmployeeMini> EmployeeList
{
get { return _EmployeesList; }
set { _EmployeesList = value; }
}
}
Now I want to access these holidays in individual employee mini i.e. for individual employee.
How can i do that?
Regards
Abhishek
This code clearly does not show any relationship between Employees and Holidays. You may simplify this further by associating each EmployeeMini with HolidaysList and then creating a list of EmployeeMini, as:
public class EmployeeMini
{
// ...
private List<HolidayCalendar> _Holidays = new List<HolidayCalendar>();
// ...
}
public class CorporateTeamTimeSheetTotalsForSpecifiedTimeFrame
{
private List<EmployeeMini> _EmployeesList = new List<EmployeeMini>();
public List<EmployeeMini> EmployeeList
{
get { return _EmployeesList; }
set { _EmployeesList = value; }
}
}
Assuming _Holidays is a list of employee holidays and not company holidays.
Please take this solution as a starting point and not as a copy-paste solution.
Edit:
If data of holidays is same for all employees, you may create a separate entity Holidays. You do not have to associate this with the employees. This seems to be a TimeSheet application.
You may associate time entries with Employees, Tasks (which is generally the case) and Holidays.
It's a pleasure to see how much knowledge people have on here, it's a treasure of a place.
I've seen myself writing code for DataGridView events - and using DataSource to a backend prepared DataTable object.
Sometimes the user can remove rows, update them etc. and the underlying data will need validation checks again.
Let's assume we have a person class
class Person {
public string FirstName { get; set; }
}
Let's say some other part of the code deals with creating an array of Person.
class Processor {
public static Person[] Create()
{
....
....
return person[];
}
}
And this information would appear on a DataGridView for user viewing.
I've tried something like this:
public static DataTable ToTable(List<Person> list)
{ ... }
And had this method in the Person class .. which I would think it'd belong to. Then I would bind the DataGridView to that DataTable and the user will then see that data and do their tasks.
But I've thought of using BindingList<> which I'm not so educated on yet.. would I still have the same capability of sorting the DataGridView like it does with DataTable as a DataSource? Would BindingList be implemented by a container class like "PersonCollection" or would the Person class implement itself? I would like to fire some events to be able to modify the collection in a clean way without having to reset datasources, etc. Where the user experience could really be affected.
I understand that modifying the DataSource DataTable is the good way. But sometimes I need to fire methods in the corresponding class that that specific row refers to, and had an ugly extra hidden column which would hold a reference to the existing object somewhere else (the Person reference).
If you guys know a better design solution, I would be more than happy to hear it.
Thanks in advance,
PS. After reading "The Pragmatic Programmer", I just can't stop thinking critically about code!
Leo B.
Create a business object class. Implement INotifyPropertyChanged. Look at the code below:
public class Employee:INotifyPropertyChanged
{
public Employee(string Name_, string Designation_, DateTime BirthDate_)
{
this.Name = Name_;
this.Designation = Designation_;
this.BirthDate = BirthDate_;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
[DisplayName("Employee Name")]
public string Name
{
get { return this._Name; }
set
{
if (value != this._Name)
{
this._Name = value;
NotifyPropertyChanged("Name");
}
}
}
private string _Name = string.Empty;
[DisplayName("Employee Designation")]
public string Designation
{
get { return this._Designation; }
set
{
if (value != this._Designation)
{
this._Designation = value;
NotifyPropertyChanged("Designation");
}
}
}
private string _Designation = string.Empty;
public DateTime BirthDate
{
get { return this._BirthDate; }
set
{
if (value != this._BirthDate)
{
this._BirthDate = value;
NotifyPropertyChanged("BirthDate");
}
}
}
private DateTime _BirthDate = DateTime.Today;
[DisplayName("Age")]
public int Age
{
get
{
return DateTime.Today.Year - this.BirthDate.Year;
}
}
}
Create your custom collection:
public class EmployeeCollection:BindingList<Employee>
{
public new void Add(Employee emp)
{
base.Add(emp);
}
public void SaveToDB()
{
//code to save to db
}
}
Set the data source:
_employeeStore = new EmployeeCollection();
this.dataGridView1.DataBindings.Add("DataSource", this, "EmployeeStore");
Now if you want to add an employee to your datagridview,
Employee employee = new Employee(textBoxName.Text, textBoxDesignation.Text, dateTimePicker1.Value);
_employeeStore.Add(employee);
This is very clean. You just play with business object and don't touch the UI.
Havent read you question fully, bbut you might want to take a look at my Project ModelShredder, which provides a convinient and fast ToDataTable method