我正准备开始一个新的 ASP.NET Web 项目,并且我将使用 LINQ-to-SQL。我已经做了一些工作,使用我找到的一些信息来设置我的数据层 迈克·哈德洛 它使用接口和泛型为数据库中的每个表创建一个存储库。起初我认为这是一个有趣的方法。但是,现在我认为创建一个 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
}
有帮助吗?

解决方案

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

然后只需向您的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/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top