質問

新しい 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