实体框架的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);

在我这样做之前,我在网上搜索了一下,看看是否已经存在这样的类,但我没有找到任何。因此,如果有人知道已经用这些函数创建了一个类,我很乐意使用它。

实体框架的DbManager助手类

我通常将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()

注意:不要忘记在您的存储库中注入:)

实体框架已经使用存储库和工作单元设计模式,不需要助手来使用该框架