【问题标题】:Repository Pattern Implementation Experience存储库模式实施经验
【发布时间】:2010-09-11 06:14:54
【问题描述】:

我正准备开始一个新的 asp.net Web 项目,我打算使用 LINQ-to-SQL。我已经使用Mike Hadlow 找到的一些信息完成了一些工作来设置我的数据层,这些信息使用接口和泛型为数据库中的每个表创建一个存储库。起初我认为这是一种有趣的方法。但是,现在我认为创建一个基础 Repository 类并从它继承以为我需要访问的表创建一个 TableNameRepository 类可能更有意义。

哪种方法可以让我以干净可测试的方式添加特定于表的功能?这是我的存储库实现供参考。

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
}

【问题讨论】:

  • 你不是在问一个具体的问题。
  • 明确您的问题,否则将作为“不是真正的问题”而关闭

标签: c# design-patterns linq-to-sql repository-pattern


【解决方案1】:

您不应该为每个表都创建一个存储库。
相反,您应该为域模型中存在的每个“实体根”(或聚合根)创建一个存储库。您可以在此处了解有关该模式的更多信息并查看一个工作示例:

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

【讨论】:

    【解决方案2】:

    我很想建议您是否使用具体类型无关紧要,就好像您使用依赖注入(城堡?)来创建存储库(这样您就可以用不同的缓存等包装它们)然后您的无论您采用哪种方式,代码库都不会更明智。

    然后只需向您的 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 的内容很有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2015-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多