代码之家  ›  专栏  ›  技术社区  ›  Hector Minaya

如何在实体框架应用程序的基类中实现crud操作?

  •  3
  • Hector Minaya  · 技术社区  · 14 年前

    我正在使用一个简单的ef/mvc应用程序,我正在尝试实现一些存储库来处理我的实体。我已经设置了一个baseobject类和一个ibaserepository接口来处理最基本的操作,所以我不必每次都重复:

    public abstract class BaseObject<T>
        {
            public XA.Model.Entities.XAEntities db;
            public BaseObject()
            {
                db = new Entities.XAEntities();
            }
    
            public BaseObject(Entities.XAEntities cont)
            {
                db = cont;
            }
    
            public void Delete(T entity)
            {
                db.DeleteObject(entity);
                db.SaveChanges();
            }
    
            public void Update(T entity)
            {
                db.AcceptAllChanges();
                db.SaveChanges();
            }
       }
    
        public interface IBaseRepository<T>
        {
            void Add(T entity);
    
            T GetById(int id);
            IQueryable<T> GetAll();
        }
    

    但是我发现自己必须在每个存储库中实现3个基本方法(add、getbyid&getall):

    public class AgencyRepository : Framework.BaseObject<Agency>, Framework.IBaseRepository<Agency>
        {
            public void Add(Agency entity)
            {
                db.Companies.AddObject(entity);
                db.SaveChanges();
            }
            public Agency GetById(int id)
            {
                return db.Companies.OfType<Agency>().FirstOrDefault(x => x.Id == id);
            }
            public IQueryable<Agency> GetAll()
            {
                var agn = from a in db.Companies.OfType<Agency>()
                          select a;
                return agn;
            }
        }
    

    我怎样才能把它们放到我的baseobject类中,这样我就不会和dry发生冲突。

    4 回复  |  直到 14 年前
        1
  •  1
  •   moribvndvs    12 年前

    嗨,我也遇到了同样的问题。想出这样的解决办法

    namespace ABC
    {
        public class EntitiesRepository<T> : IDisposable where T : class
        {
            private ObjectContext _context;
    
            /// <summary>
            /// The IObjectSet that represents the current entity.
            /// </summary>
            private ObjectSet<T> _objectSet;
    
            public OperationStatus status { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the DataRepository class
            /// </summary>
            public BilderQuizEntitiesRepository()
            {
                _context = new Entities();  //DBContext
    
                _objectSet = _context.CreateObjectSet<T>();
             }
    
            public T Select(int id)
            {
                EntityKey key = GetEntityKey(id);
    
                return (T)_context.GetObjectByKey(key);
            }
    
            public void Delete(T entity)
            {
                try
                {
                    if (entity == null)
                    {
    
                        throw new ArgumentNullException("entity");
                    }
    
                    EntityKey key = GetEntitySpecificKey(entity);
                    T attachEntity = (T)_context.GetObjectByKey(key);
                    _objectSet.DeleteObject(attachEntity);
                    SaveChanges();                
                }
                catch
                {
    
                }
    
            }       
    
            public void Delete(int id)
            {
                EntityKey key = GetEntityKey(id);
                Delete((T)_context.GetObjectByKey(key));
                SaveChanges();
            }
    
            public void Update(T entity)
            {
                try
                {
                    if (entity == null)
                    {
    
                        throw new ArgumentNullException("entity");
                    }
    
                    EntityKey key = GetEntitySpecificKey(entity);
                    T attachEntity = (T)_context.GetObjectByKey(key);
                    _objectSet.Attach(attachEntity);
                    _objectSet.ApplyCurrentValues(entity);
                    SaveChanges();
    
                }
                catch
                {
    
                }
    
            }       
    
            /// <summary>
            /// Returns Entity Key 
            /// </summary>
            /// <param name="keyValue"></param>
            /// <returns></returns>
            private EntityKey GetEntityKey(object keyValue) //Get EnrityKey
            {
                var entitySetName = _context.DefaultContainerName + "." + _objectSet.EntitySet.Name;
                var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
                var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
                return entityKey;
            }
    
            /// <summary>
            /// Returns Entity Key 
            /// </summary>
            /// <param name="keyValue"></param>
            /// <returns></returns>
            private EntityKey GetEntitySpecificKey(T entity) //Get EnrityKey
            {
                Type objType = typeof(T);
                var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
                var pi = objType.GetProperty(keyPropertyName);
                var keyValue = pi.GetValue(entity, null);
                var entitySetName = _context.DefaultContainerName + "." + _objectSet.EntitySet.Name;
    
                var entityKey = new EntityKey(entitySetName, new[] { new EntityKeyMember(keyPropertyName, keyValue) });
                return entityKey;
            }
    
            private string GetPrimaryKeyValue(T entity)
            {
                Type objType = typeof(T);
                var keyPropertyName = _objectSet.EntitySet.ElementType.KeyMembers[0].ToString();
                var pi = objType.GetProperty(keyPropertyName);
                var keyValue = pi.GetValue(entity, null);
                return keyValue.ToString();
            }
    
            /// <summary>
            /// Saves all context changes
            /// </summary>
            public bool SaveChanges()
            {
                return _context.SaveChanges() > 0 ? true : false;
            }
    
            /// <summary>
            /// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
            /// </summary>
            public void Dispose()
            {
    
                Dispose(true);
    
                GC.SuppressFinalize(this);
    
            }
    
            /// <summary>
            /// Releases all resources used by the WarrantManagement.DataExtract.Dal.ReportDataBase
            /// </summary>
            /// <param name="disposing">A boolean value indicating whether or not to dispose managed resources</param>
            protected virtual void Dispose(bool disposing)
            {
    
                if (disposing)
                {
    
                    if (_context != null)
                    {
    
                        _context.Dispose();
    
                        _context = null;
    
                    }
    
                }
    
            }
        }
    
    }
    

    如果你能找到更好的方法

        2
  •  0
  •   Josh Sterling    14 年前

    除非您的基类能够实现接口(然后您可以继承它的实现),否则每次编写它们都很麻烦。如果每个孩子的步骤都不一样,那么你就不要重复自己的步骤,尽管这有点像。

    作为一个主题外的注释,与其在基本构造函数中创建db对象,还不如省去一些麻烦,然后依赖注入它。如果您将任何值得测试的代码放在存储库中,它将使您的存储库更易于单元测试。

        3
  •  0
  •   Craig Stuntz    14 年前

    在EF4中使用T4很容易做到这一点。有了更多的工作,你就可以在ef 1中使用t4。

    但我建议你不要。 MyEntity.Update() 会是虚构的。ef不允许您将部分更改保存到上下文(如一个特定对象)。所以你的方法会做一些和看起来很不一样的事情。我知道这个设计是针对EF的。它还通过设计使您的实体能够感知持久性。

        4
  •  0
  •   diegoe    9 年前

    这是一个老问题,但它仍然是开放的,所以也许它是有帮助的人。针对这种情况,我的解决方案是使用一个abstrat类和实现基本操作(如选择、插入、更新或删除)的泛型类型。

    我的基类是这样的:

    public abstract class MyContext<T, key> : IDisposable where T : class {
    
        private DbEntities db;    //my database context
        private DbSet<T> entities;  //specific set
    
        protected MyContext(DbEntities db) {
            entities = db.Set<T>();
            this.db = db;
        }
    
        public T Add(T entity) {
            entities.Add(entity);
            db.SaveChanges();
            return entity;
        }
    
        public T Get(key id) {
            return entities.Find(id);
        }
    
        public List<T> GetAll() {
            return entities.ToList();
        }
    
        public void Delete(key id) { 
            T objectToDelete=entities.Find(id);
            if(objectToDelete!=null){
                entities.Remove(objectToDelete);
                db.SaveChanges();
            }  
        }
    
        public void Delete(T entity) {
            entities.Remove(entity);
            db.SaveChanges();
        }
    
        public void Delete(List<T> items) {
            foreach (T entity in items) {
                entities.Remove(entity);
            }
            db.SaveChanges();
        }
    
        public void Update(T entity) {
            entities.Attach(entity);
            db.Entry(entity).State = EntityState.Modified;
            db.SaveChanges();
        }
    
        public abstract void Dispose();
    }
    

    具体实例类

    public class PermissionDataBase : MyContext<Permission,int>{  
        //Mapped class Permission where the key is int
    
        private DbEntities db=null;
    
        public PermissionDataBase(DbEntities db):base(db) {
            this.db = db;
        }
    
        //Additional methods (if required)
        public Permission FindByName(string name) {
            return db.Permissions.FirstOrDefault(p => p.Name == name);
        }
    
        public override void Dispose() {
            db.Dispose();
        }
    }
    

    测试

    public class ModelsTest {
        [TestMethod]
        public void TestMethod1() {
            DbEntities db = new DbEntities();
            using (PermissionDataBase permissionDb = new PermissionDataBase(db)) {
    
                Permission newEntity = new Permission() {
                    Name = "Test1"
                };
    
                permissionDb.Add(newEntity);
    
                Assert.IsTrue(newEntity.Id > 0);
            }
        }
    
        [TestMethod]
        public void TestMethod2() {
            DbEntities db = new DbEntities();
            using (PermissionDataBase permissionDb = new PermissionDataBase(db)) {
    
                List<Permission> items = permissionDb.GetAll();
                Assert.IsTrue(items.Count > 0);
            }
        }
    
        [TestMethod]
        public void TestMethod3() {
            DbEntities db = new DbEntities();
            using (PermissionDataBase permissionDb = new PermissionDataBase(db)) {
    
                Permission toDelete = permissionDb.Get(3);  //Assuming id=3 exists
                permissionDb.Delete(toDelete);
    
                Permission deleted = permissionDb.Get(3);
                Assert.IsNull(deleted);
            }
        }
    }
    

    此代码适用于Visual Studio Community 2013中的实体框架5。