实体框架的DbManager帮助器类

时间:2014-07-31 09:24:38

标签: c# entity-framework dbcontext

我正在尝试使用通用的Db cotext helper \ manager,因此我可以在许多具有不同数据库的项目中将其用作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();
        }
    }

编辑:尝试更好地解释我正在做什么。

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);

在我这样做之前,我搜索了互联网,看看这样的课程是否已经存在,但我没有找到。因此,如果有人知道已经使用这些功能制作的课程,我很乐意使用它。

4 个答案:

答案 0 :(得分:0)

我更喜欢做以下事情:

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();
    }

很容易修改此代码以使用模型。

答案 1 :(得分:0)

我通常使用Repository和UnitOfWork模式。

尝试实现这样的基础存储库,然后使用相同的方法创建派生实体类型。

这有助于保持代码干净。

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

答案 2 :(得分:0)

为什么重新发明轮子。尝试NRepository,它是一个通用的存储库(是的,另一个),具有实体框架扩展,并使用策略进行重用,而不是服务方法。在没有模拟的情况下使用它完全可测试。

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()

N.B。不要忘记注入您的存储库:)

答案 3 :(得分:0)

实体框架已经使用了存储库和工作单元设计模式,无需帮助者使用该框架

相关问题