3

DBContextを使用してEFとインターフェイスする汎用リポジトリを作成しています。

主キー値を受け取り、エンティティを返す汎用のGet()メソッドがあります。

public class DALRepository<DALEntity> : IDisposable, IGenericRepository<DALEntity> where DALEntity : class
{
private IDbSet<DALEntity> dbSet;
private NWEntities context;

public DALRepository()
{
  context = new NWEntities();
  context.Configuration.LazyLoadingEnabled = false;
  dbSet = context.Set<DALEntity>();
}

これが簡単なgetメソッドです-PKで動作します-まさに私が欲しいものです。

public DALEntity Get(string ID)
{
   return dbSet.Find(ID);
}

これを変更して、消費者がインクルードのリストを渡すことができるようにします。これにより、顧客だけを返品するだけでなく、注文の返品もリクエストできます。ここで私は問題にぶつかっています。私がこれを行う場合:

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null)
{
      IQueryable<DALEntity> query = dbSet;
      query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath));
}

IQueryableでfindを使用できません。また、includesを渡すことができないため、Find()を直接見つけることはできません。IQueryableで代わりにwhereラムダを使用する場合、エンティティのPKを使用するように指示するにはどうすればよいですか?ジェネリック型は「ID」などの明確に定義されたプライマリ列名を持つIPkeyインターフェイスを実装する必要があると主張するジェネリック制約があると思いますが、DBContextによって生成されたエンティティは実装する必要があるため使用できませんこのインターフェース。必要に応じてT4を変更してこれを行うことができます-そして、XMLコメントを発行するようにすでに変更しているので、それを嫌うことはありません-しかし、誰かがもっと簡単な方法を持っていますか?私が必要としているのは、インクルードのリストを受け入れるオーバーロードされたfind()だと思います。

だから私の質問は、インクルードで検索を使用する方法、またはPKを知っているラムダを書く方法のいずれかです。このようなラムダをパラメーターとして受け取ることはできません。これは、最終的にWCFサービスによって消費されるためです。

4

3 に答える 3

2

あなた自身の質問に答えるのはちょっと変ですが、他の誰かがこの問題を抱えている場合に備えて、私がしたことは次のとおりです。私は動的LINQのものを使用し、.Where()の文字列オーバーロードバージョンを使用しました。前述のリンクの 1 つを使用して、主キーを取得する方法を見つけました (私のものも DBContext からのものです)。メソッドは次のようになります。

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null)
{
  var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<DALEntity>();
  var entitySet = set.EntitySet;
  string[] keyNames = entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();
  Debug.Assert(keyNames.Length == 1, "DAL does not work with composite primary keys or tables without primary keys");

  IQueryable<DALEntity> query = dbSet;
  query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath));

  query = query.Where(keyNames[0] + "= @0", ID);
  return query.FirstOrDefault();
}
于 2012-10-26T03:04:30.123 に答える
0

オブジェクトを検索できるLinq のSingleまたはFirstIQueryableメソッドを使用します。

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null)
{
      IQueryable<DALEntity> query = dbSet;
      query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath));
      query = query.Single(x=>x.Id == ID);
}
于 2012-10-25T10:01:49.973 に答える
0

ここで説明されている方法でキーを動的に取得できます:https://stackoverflow.com/a/10796471/971693

そうは言っても、リフレクションを使用しないと方法がわかりません。

public IEnumerable<DALEntity> Get(params string IDs)
{
   var objectSet = objectContext.CreateObjectSet<YourEntityType>();
   var keyNames = objectSet.EntitySet.ElementType.KeyMembers.First(k => k.Name);

   return dbSet.Where(m => ID.Contains((string)m.GetType().GetProperty(keyNames ).GetValue(m, null));
}

まず、params string IDs を使用すると、1 つ以上の ID を渡すことができ、文字列の配列になります。関数の最初の部分は、主キーの名前を動的に取得することです。

2 番目の部分では、パラメーターで受け取った ID の配列内に主キー値 (リフレクションによって取得) が含まれているセットからすべての要素を返すクエリを作成します。

于 2012-10-25T00:38:28.443 に答える