代码之家  ›  专栏  ›  技术社区  ›  Phil.Wheeler

与Entity Framework/Linq to SQL正确使用接口

  •  0
  • Phil.Wheeler  · 技术社区  · 16 年前

    我将要在这里展示我的缺乏经验,但是,就像我想学习的任何开发人员一样。

    给定以下接口:

    public interface IRepository
    {
        entityDB Database { get; set; }
    
        IQueryable<T> All<T>() where T:class, new();
        T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
        IList<T> Find<T>(Expression<Func<T, bool>> expression) where T : class, new();
    }
    

    如何创建可用的存储库类,以便用强类型替换泛型类型T?

    假设我有一个照片组合站点,它有一个照片实体和一个camerasettings实体,我该如何定义类型,从而定义包含在我的具体类中的L2s?当前,当我实现类时,它需要以下形式:

    public class PhotoRepository : IRepository
    {
        public override IQueryable<T> All<T>()
        {
            // code goes here...
        }
    
        public override T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression)
        {
            // ...and here...
        }
    
        public override IList<T> Find<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression)
        {
            // ... and let's not forget here.
        }
    }
    

    我这样做是正确的,还是应该使用如下界面:

    public interface IRepository<T> where T:class
    {
        entityDB Database { get; set; }
    
        IQueryable<T> All();
        T Single<T>;
        IList<T> Find();
    }
    

    我只想让我的单元测试正常工作,并且确信我没有学习坏的(或者只是很难看的)习惯。欣赏正确方向的转向。

    2 回复  |  直到 12 年前
        1
  •  2
  •   bniwredyc    16 年前

    如果我对您的理解是正确的,那么您需要为每个实体(或仅为其中一些实体)创建单独的存储库。在这种情况下,适当的解决方案是使用发布的接口的第二个版本。这样地:

    public interface IRepository<T> where T : class, new()
    {
        entityDB Database { get; set; }
    
        IQueryable<T> All();
        T Single(Expression<Func<T, bool>> expression);
        IList<T> Find(Expression<Func<T, bool>> expression);
    } 
    

    以及 PhotoRepository 将如下所示:

    public class PhotoRepository : IRepository<Photo>
    {
        public IQueryable<Photo> All()
        {
            // code goes here...
        }
    
        public Photo Single(Expression<Func<Photo, bool>> expression)
        {
            // ...and here...   
        }
    
        public IList<Photo> Find(Expression<Func<Photo, bool>> expression)
        {
            // ... and let's not forget here.   
        }
    }
    

    此外,如果您的存储库将与实体框架实体一起操作,则可以更准确地定义iRepository接口:

    public interface IRepository<T> where T : EntityObject, new()
    
        2
  •  2
  •   LukLed    16 年前

    在我的项目中,我创建了自己的iRepository:

    public interface IRepository<T>
    {
        //Retrieves list of items in table
        IQueryable<T> List();
        IQueryable<T> List(params string[] includes);
        //Creates from detached item
        void Create(T item);
        void Delete(int id);
        T Get(int id);
        T Get(int id, params string[] includes);
        void SaveChanges();
    }
    

    以下是通用实现:

    public class Repository<T> : IRepository<T> where T : EntityObject
    {
        private ObjectContext _ctx;
    
        public Repository(ObjectContext ctx)
        {
            _ctx = ctx;
        }
    
    
        private static string EntitySetName
        {
            get
            {
                return String.Format(@"{0}Set", typeof(T).Name);
            }
        }
    
        private ObjectQuery<T> ObjectQueryList()
        {
            var list = _ctx.CreateQuery<T>(EntitySetName);
            return list;
        }
    
        #region IRepository<T> Members
    
        public IQueryable<T> List()
        {
            return ObjectQueryList().OrderBy("it.ID").AsQueryable();
        }
    
        public IQueryable<T> List(params string[] includes)
        {
            var list = ObjectQueryList();
    
            foreach(string include in includes)
            {
                list = list.Include(include);
            }
    
            return list;
        }
    
        public void Create(T item)
        {
            _ctx.AddObject(EntitySetName, item);
        }
    
        public void Delete(int id)
        {
            var item = Get(id);
            _ctx.DeleteObject(item);
        }
    
        public T Get(int id)
        {
            var list = ObjectQueryList();
            return list.Where("ID = @0", id).First();
        }
    
        public T Get(int id, params string[] includes)
        {
            var list = List(includes);
            return list.Where("ID = @0", id).First();
        }
    
        public void SaveChanges()
        {
            _ctx.SaveChanges();
        }
    
        #endregion
    
    }
    

    如果需要简单的存储库,只需使用 Repository<ClassName> . 如果你想增强它,你可以 define ClassNameRepository : Repository<ClassName> 写另一种方法。你不必定义 List() 方法,因为它是在基本库中完成的。在编写存储库之前,我做了假设:

    • 数据库中的每个主键字段都称为ID。
    • 每个EntitySetName都是从类名和 Set . 为了 User 它将是类 UserSet .

    此解决方案使用动态LINQ:

    http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

    它工作得很好。