版本库模式实施经验

问题描述:

我正准备开始一个新的asp.net web项目,并且我要去LINQ到SQL。我已经完成了一些工作,使用我在Mike Hadlow中发现的一些信息来获取数据层设置,这些信息使用Interface和泛型为数据库中的每个表创建一个Repository。起初我认为这是一个有趣的方法。然而,现在我认为创建一个基本Repository类并从它继承来为我需要访问的表创建一个TableNameRepository类会更有意义。版本库模式实施经验

哪种方法将允许我以清洁可测试的方式添加特定于表格的功能?这是我的Repository实现供参考。

public class Repository<T> : IRepository<T> where T : class, new() 
{ 
    protected IDataConnection _dcnf; 

    public Repository() 
    { 
     _dcnf = new DataConnectionFactory() as IDataConnection; 
    } 

    // Constructor injection for dependency on DataContext 
    // to actually connect to a database 
    public Repository(IDataConnection dc) 
    { 
     _dcnf = dc; 
    } 

    /// <summary> 
    /// Return all instances of type T. 
    /// </summary> 
    /// <returns>IEnumerable<T></returns> 
    public virtual IEnumerable<T> GetAll() 
    { 
     return GetTable; 
    } 

    public virtual T GetById(int id) 
    { 
     var itemParam = Expression.Parameter(typeof(T), "item"); 
     var whereExp = Expression.Lambda<Func<T, bool>> 
      (
       Expression.Equal(
        Expression.Property(itemParam, PrimaryKeyName), 
        Expression.Constant(id) 
       ), new ParameterExpression[] { itemParam } 
      ); 
     return _dcnf.Context.GetTable<T>().Where(whereExp).Single(); 
    } 

    /// <summary> 
    /// Return all instances of type T that match the expression exp. 
    /// </summary> 
    /// <param name="exp"></param> 
    /// <returns>IEnumerable<T></returns> 
    public virtual IEnumerable<T> FindByExp(Func<T, bool> exp) 
    { 
     return GetTable.Where<T>(exp); 
    } 

    /// <summary>See IRepository.</summary> 
    /// <param name="exp"></param><returns></returns> 
    public virtual T Single(Func<T, bool> exp) 
    { 
     return GetTable.Single(exp); 
    } 

    /// <summary>See IRepository.</summary> 
    /// <param name="entity"></param> 
    public virtual void MarkForDeletion(T entity) 
    { 
     _dcnf.Context.GetTable<T>().DeleteOnSubmit(entity); 
    } 

    /// <summary> 
    /// Create a new instance of type T. 
    /// </summary> 
    /// <returns>T</returns> 
    public virtual T Create() 
    { 
     //T entity = Activator.CreateInstance<T>(); 
     T entity = new T(); 
     GetTable.InsertOnSubmit(entity); 
     return entity; 
    } 

    /// <summary>See IRepository.</summary> 
    public virtual void SaveAll() 
    { 
     _dcnf.SaveAll(); 
    } 

    #region Properties 
    private string PrimaryKeyName 
    { 
     get { return TableMetadata.RowType.IdentityMembers[0].Name; } 
    } 

    private System.Data.Linq.Table<T> GetTable 
    { 
     get { return _dcnf.Context.GetTable<T>(); } 
    } 

    private System.Data.Linq.Mapping.MetaTable TableMetadata 
    { 
     get { return _dcnf.Context.Mapping.GetTable(typeof(T)); } 
    } 

    private System.Data.Linq.Mapping.MetaType ClassMetadata 
    { 
     get { return _dcnf.Context.Mapping.GetMetaType(typeof(T)); } 
    } 
    #endregion 
} 
+0

你是不是问一个具体问题。 – ddaa 2008-09-19 14:24:30

我会忍不住表明您是否使用的具体类型或不应该没关系,因为如果你的使用依赖注入(城堡?)来创建存储库(这样你就可以用不同的缓存将它们包装等等),那么你的代码库不会更聪明,无论你做了什么。

然后,只要问你的DI存储库。例如。对于城堡:

public class Home { 
    public static IRepository<T> For<T> { 
    get { 
     return Container.Resolve<IRepository<T>>(); 
    } 
    } 
} 

就我个人而言,直到你找到需要的时候,

我想你的问题的另一半是你是否可以轻松地提供内存实现的IRepository进行测试和缓存的目的。为此,我会留意,因为linq-to-objects可能会很慢,您可能会发现像http://www.codeplex.com/i4o这样有用的东西。

您不应该为每个表创建存储库。
相反,您应该为您的域模型中存在的每个“实体根”(或聚合根)创建一个存储库。您可以了解更多的模式,在这里看到一个工作例子:

http://deviq.com/repository-pattern/