实体框架的DbManager助手类
本文关键字:DbManager 框架 实体 | 更新日期: 2023-09-27 18:15:42
我正在尝试做一个通用的Db上下文助手'管理器,这样我就可以在许多具有不同数据库的项目中使用它作为dll。
我试图在我的一个项目中使用它,但我对添加和编辑方法中的附加和分离感到困惑。我得到的错误是"一个实体对象不能被IEntityChangeTracker的多个实例引用。"
谁能帮我让这个经理变得完美?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();
}
}
EDIT:试图更好地解释我所指的内容。
IEntity是一个接口,只是为了能够使用GetObjectById函数:
public interface IEntity
{
int Id { get; }
}
下面是一个类的例子:
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 class AddressManager : DbEntityManager<Address>
{
public AddressManager()
: base (new MySystemEntities())
{
}
}
然后使用它的代码(在winform/mvc或其他):
AddressManager manager = new AddressManager ();
Address address = new Address();
address = manager.GetObjectById(id);
或:
Address address = new Address();
address.Address_Country = "USA";
manager.AddNewObject(address);
在我这样做之前,我在网上搜索了一下,看看是否已经存在这样的类,但我没有找到任何。因此,如果有人知道已经用这些函数创建了一个类,我很乐意使用它。
我通常将Repository与UnitOfWork模式一起使用。
尝试实现这样的基础存储库,然后使用相同的存储库创建派生实体类型。
这将有助于保持代码DRY。
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操作。
,http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
我更喜欢这样做:
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();
}
为什么要重新发明轮子呢?试试NRepository,它是一个通用的存储库(是的,另一个),具有实体框架扩展,并使用重用策略而不是服务方法。另外,它是完全可测试的,不需要mock。
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()
注意:不要忘记在您的存储库中注入:)
实体框架已经使用存储库和工作单元设计模式,不需要助手来使用该框架