私の UnitOfWork には、エンティティの種類ごとにリポジトリがあり、集約ルートを使用していないことがわかったので、それを修正しようとしています。コンピューター インベントリのアイデアに取り組み、現在 UnitOfWork を次のように構成しています。
public class UnitOfWork : IUnitOfWork
{
private readonly ReportingDbContext _dbContext = null;
public UnitOfWork()
{
_dbContext = new ReportingDbContext();
}
public void Commit()
{
_dbContext.SaveChanges();
}
// Inventory
public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }}
public IRepository<NetworkAdapterEntity> NetworkAdapters { get { return new Repository<NetworkAdapterEntity>(_dbContext); } }
// plus a bunch more
}
集計ルートだけをそこに表示したいのですが、これは簡単に実行できるはずです。問題は、単一のリポジトリ クラスを使用していて、新しいものを作成するときにそのタイプをフィードしていることだと思います。答えは、それぞれが集約ルートに対応する複数のリポジトリを持つことだと思います。各タイプに使用しているこの 1 つの汎用リポジトリの優れている点は、ID による検索、DbSet への保存など、すべての Entity Framework を処理できることです。私の汎用リポジトリは次のように設定されています。
public class Repository<T> : IRepository<T> where T : class
{
protected DbContext DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public Repository(DbContext dbContext)
{
if (dbContext == null)
{
throw new ArgumentNullException("dbContext");
}
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public IQueryable<T> Find(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
// the rest of the implementation omitted for brevity
}
このリポジトリは、まだ作成されていないすべての集約ルート リポジトリが使用する必要があるインターフェイスを使用します。
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
T GetById(int id);
void Remove(T entity);
void Add(T newEntity);
}
ここからが本題です。上記のインターフェイスを具体的な Repository クラスに適切に実装しました。これから作成するすべての集約ルート リポジトリで同じ機能を使用したいと考えています。Entity Framework で行う基本的な CRUD を取得するためのベースとして使用したいだけなので、この汎用リポジトリを直接使用したくはありません。すでに実装されている一般的なリポジトリのものを繰り返したくありません。継承するだけです。さらに重要なことは、これを最初から正しく設計したいということです。
集計ルートベースのリポジトリを次のように作成するのが適切でしょうか:
public interface IComputerRepository
{
string ComputerSpecificMethod(string param);
}
public class ComputerRepository : Repository<ComputerEntity>, IComputerRepository
{
public ComputerRepository(DbContext dbContext) : base(dbContext)
{
//
}
public string ComputerSpecificMethod(string param)
{
// do stuff
return "test";
}
}
次に、UnitOfWork でこの新しいファンシー リポジトリ (およびその他の同様のリポジトリ) を次のように使用します。
public IRepository<ComputerEntity> Computers {get { return new ComputerRepository(_dbContext); }}
それ以外の:
public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }}
目標は UnitOfWork/Repository パターンに固執することですが、これが適切な方法であるかどうかはわかりません。