C# 实体框架的DbManager助手类
我正在尝试做一个通用的Db cotext helper\manager,这样我就可以在许多具有不同数据库的项目中使用它作为dll 我曾尝试在我的一个项目中使用它,但我对Add和Edit方法中的attach和detach感到困惑。由于entity对象不能被多个IEntityChangeTracker实例引用,我遇到了错误 有人能帮我把这位经理弄得十全十美吗C# 实体框架的DbManager助手类,c#,entity-framework,dbcontext,C#,Entity Framework,Dbcontext,我正在尝试做一个通用的Db cotext helper\manager,这样我就可以在许多具有不同数据库的项目中使用它作为dll 我曾尝试在我的一个项目中使用它,但我对Add和Edit方法中的attach和detach感到困惑。由于entity对象不能被多个IEntityChangeTracker实例引用,我遇到了错误 有人能帮我把这位经理弄得十全十美吗 public class DbEntityManager<T> : IDisposable where T : class, IE
public class DbEntityManager<T> : IDisposable where T : class, IEntity
{
public DbContext DbEntities { get; set; }
public virtual int AddNewObject(T objToAdd)
{
DbEntities.Set<T>().Add(objToAdd);
return DbEntities.SaveChanges();
}
public virtual int EditObject(T objToEdit)
{
if (DbEntities.Entry(objToEdit).State == EntityState.Detached)
{
DbEntities.Set<T>().Attach(objToEdit);
DbEntities.Entry(objToEdit).State = EntityState.Modified;
}
else
{
DbEntities.Entry(objToEdit).State = EntityState.Modified;
}
return DbEntities.SaveChanges();
}
public virtual int DeleteObject(T objToDelete)
{
DbEntities.Set<T>().Remove(objToDelete);
return DbEntities.SaveChanges();
}
public virtual List<T> GetAllList()
{
return DbEntities.Set<T>().ToList();
}
public virtual T GetObjectById(int id)
{
return DbEntities.Set<T>().AsEnumerable().SingleOrDefault(x => x.Id == id);
}
public DbEntityManager(DbContext db)
{
DbEntities = db;
}
public void Dispose()
{
this.Dispose();
}
}
下面是一个类的示例:
public partial class Address : IEntity
{
public Address()
{
this.Customers = new HashSet<Customer>();
}
public int AddressID { get; set; }
public string Address_Country { get; set; }
public string Address_City { get; set; }
public string Address_Street { get; set; }
public string Address_ZipCode { get; set; }
public virtual ICollection<Customer> Customers { get; set; }
public int Id
{
get { return AddressID; }
}
}
或:
在我这么做之前,我在互联网上搜索了一下,看看是否已经存在这样的类,但我没有找到任何类。因此,如果有人知道已经用这些函数创建了一个类,我很乐意使用它。我更喜欢做以下事情:
public virtual int EditObject(T objToEdit)
{
var curval = DB.Set<T>().FirstOrDefault(x => x.Id == objToEdit.Id);
//You may want to make all your entities inherit from the same
//baseclass to get Id
if (curval == null)
{
DB.Set<T>.Add(objToEdit);
}
else
{
DB.Entry(curval).CurrentValues.SetValues(objToEdit);
DB.Entry(curval).State = System.Data.Entity.EntityState.Modified;
}
return DB.SaveChanges();
}
修改此代码以处理模型也很容易。我通常将存储库与模式一起使用 尝试实现这样一个基本存储库,然后使用相同的方法创建派生实体类型 这将有助于保持代码干燥
public interface IBaseRepository<TEntity> : IDisposable
where TEntity : class
{
void Delete(object id);
void Delete(TEntity entity);
TEntity Find(params object[] keyValues);
void Insert(TEntity entity);
void InsertRange(IEnumerable<TEntity> entities);
IQueryable<TEntity> SelectQuery(string query, params object[] parameters);
void Update(TEntity entity);
void RefreshEntityContext(TEntity entity);
}
希望这有帮助
编辑:好的,下面是实现的摘录,与我实现它的方式类似:
namespace ContosoUniversity.DAL
{
public class GenericRepository<TEntity> where TEntity : class
{
internal SchoolContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(SchoolContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
}
现在,您可以从GenericRepository继承存储库,并提供所有基本CRUD操作
从,
为什么要重新发明轮子。试试看,它是一个通用的存储库,是的,另一个具有实体框架扩展,并使用重用策略而不是服务方法。另外,它完全可测试,无需模拟
IQueryRepository queryRepository = new EntityFrameworkQueryRepository(new YourDbContext()) ;
var address = queryRepository.GetEntity<Address>(
p => p.AddressID == 2,
new AsNoTrackingQueryStrategy(),
new EagerLoadingQueryStrategy<Address>(
p => p.Customers));
注意:不要忘记在您的存储库中注入:实体框架已经使用了存储库和工作单元设计模式,不需要帮助人员使用该框架为什么需要这样做?您希望从抽象中得到什么?这个问题应该更适合我所说的,我想将它用作具有不同db的许多项目的dll。我不想在每个项目中都创建添加、保存更改和所有这些。实际上,我自己也构建了类似的东西。本质上,为了回答@DeanWard的问题,它是一个完全通用的数据访问类——从FooT obj的C意义上来说,它与任何数据存储方法SQL、XML等都无关。在一个类中,我将它分为两个——通用数据管理器和将其连接到不同数据源的各种适配器。一个适配器是用于使用实体框架的SQL的,因此将完全满足您所描述的需求。如果你感兴趣的话,我打算在未来几天的某个时候把它放到NuGet上。你说这是一个围绕DbContext的包装器,但它看起来确实是围绕DbSet的包装器。你是否清楚你为什么要这样做,你的动机,在这里应该帮助我们和你自己更好地理解为什么。如果没有IEntity和DbEntities的定义,这段代码一点也不清楚。接口在这里对我没有帮助。@user2254436-你需要实现接口,就像我在我的项目中所做的那样,它促进了可重用存储库基类的实现,如上面共享的“UnitOfWork”实现中所述。你检查过这个模式了吗?
public virtual int EditObject(T objToEdit)
{
var curval = DB.Set<T>().FirstOrDefault(x => x.Id == objToEdit.Id);
//You may want to make all your entities inherit from the same
//baseclass to get Id
if (curval == null)
{
DB.Set<T>.Add(objToEdit);
}
else
{
DB.Entry(curval).CurrentValues.SetValues(objToEdit);
DB.Entry(curval).State = System.Data.Entity.EntityState.Modified;
}
return DB.SaveChanges();
}
public interface IBaseRepository<TEntity> : IDisposable
where TEntity : class
{
void Delete(object id);
void Delete(TEntity entity);
TEntity Find(params object[] keyValues);
void Insert(TEntity entity);
void InsertRange(IEnumerable<TEntity> entities);
IQueryable<TEntity> SelectQuery(string query, params object[] parameters);
void Update(TEntity entity);
void RefreshEntityContext(TEntity entity);
}
namespace ContosoUniversity.DAL
{
public class GenericRepository<TEntity> where TEntity : class
{
internal SchoolContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(SchoolContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
}
IQueryRepository queryRepository = new EntityFrameworkQueryRepository(new YourDbContext()) ;
var address = queryRepository.GetEntity<Address>(
p => p.AddressID == 2,
new AsNoTrackingQueryStrategy(),
new EagerLoadingQueryStrategy<Address>(
p => p.Customers));
IRepository repository = new EntityFrameworkRepository(new YourDbContext()) ;
var address = new Address{ Address_City = "Leeds" };
repository.Add(address);
repository.Save()