I'm new to EF, but I've been programming 21 years. I like to make things DRY and generic but something about what I've just done seems wrong but I can't put my finger on it.
Every example on EF I've seen has the developer creating 4 seperate CRUD methods for each and every POCO class. So I set out to not have to do that and this is what I came up with:
Model:
public class Model1 : DbContext
{
public Model1()
: base("name=Model1")
{
}
public virtual DbSet<Member> Members { get; set; }
}
Base class for all business tier:
using System.Data.Entity;
using System.Reflection;
namespace biz
{
public abstract class EFObject<T> where T : EFObject<T>
{
public int Id { get; set; }
internal static readonly string DbSetProperyName = typeof(T).Name + "s";
public static EFCollection<T> Collection
{
get
{
using (var db = new Model1())
{
PropertyInfo p = db.GetType().GetProperty(DbSetProperyName);
DbSet<T> collection = (DbSet<T>)p.GetValue(db);
return new EFCollection<T>(collection);
}
}
}
public void Insert()
{
using (var db = new Model1())
{
PropertyInfo p = db.GetType().GetProperty(DbSetProperyName);
DbSet<T> collection = (DbSet<T>)p.GetValue(db);
collection.Add((T)this);
db.SaveChanges();
}
}
public void Save()
{
if (Id == 0)
Insert();
else
Update();
}
public void Update()
{
using (var db = new Model1())
{
PropertyInfo p = db.GetType().GetProperty(DbSetProperyName);
DbSet<T> collection = (DbSet<T>)p.GetValue(db);
T dbItem = collection.Find(Id);
foreach (PropertyInfo pi in typeof(T).GetProperties())
{
pi.SetValue(dbItem, pi.GetValue(this));
}
db.SaveChanges();
}
}
}
}
Generic Collection class:
using System.Collections.Generic;
namespace biz
{
public class EFCollection<T> : List<T> where T : EFObject<T>
{
public EFCollection()
{
}
public EFCollection(IEnumerable<T> collection)
{
AddRange(collection);
}
public void Save()
{
foreach (T item in this)
item.Save();
}
}
}
Example middle tier class:
namespace biz
{
public class Member : EFObject<Member>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Client[] Clients;
public Good[] Goods;
public decimal Percentage;
}
}
And usage:
var member = new biz.Member() { FirstName = "Brad", LastName = "Pitt", Percentage = 1 };//
member.Save();
member = biz.Member.Collection.Find(o=>o.Id == member.Id);
member.FirstName = "Cherry";
member.Save();
The usage code works, but I'm wondering what kind of problems is this approach going to run me into?
One thing that rubs me the wrong way about what I've done is perhaps due to me now knowing EF well enough. In my update scenario, I 1) use one session to get an object from the collection, 2) disconnect, 3) update the properties of the object, 3) start a new session, 3) find the matching object by primary key from the db (it's no longer the same object!), 4) update it via reflection, then 5) save changes. So there are two objects involved not one and reflection. I think I have to "let go" of the connection to keep the original object once I get it, and I don't know how to fix this.