2010-01-15 66 views
0

我要在这里展示我的经验不足,但嘿 - 就像任何开发者,我想学习。正确的接口使用/ LINQ到SQL

考虑到如下界面:

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替换为一个强类型?

假设我有一个具有Photos实体和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(); 
} 

我只是想让我的单元测试正常工作,并确信我没有学习坏习惯(或简单丑陋)的习惯。感谢正确的方向。

+0

我不认为我需要。我同意Preben Huybrechts采取的方法。 – 2012-07-12 00:00:58

回答

2

如果我理解你的权利,你要为你的每一个实体(或只是其中的几个)创建单独的存储库。在这种情况下,适当的解决方案是使用您发布的第二个版本的界面。就像这样:

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

谢谢。作为EF的新手,我认为应该有更具体的东西来实施。 – 2010-01-15 08:22:02

2

在我的项目中,我创建了自己的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

它工作得很好。

+0

我喜欢这个。它看起来很干净而且可以重复使用。可能不得不放弃它。干杯。 – 2010-01-16 01:17:18