2011-04-26 8 views
2

params object[]をパラメータとするGeneric GetByIdを作成する方法を探しており、キー/ sフィールドを見つけ、関連するエンティティを見つけることがわかっています。私はPKフィールドの定義およびフィールドに基づいてエンティティを返すことができる汎用的な方法を返す一般的な方法について考えて解決策を見つけるようにして複合体の汎用GetById

私は主キーとして1つ以上のフィールドを持つテーブルで使用できる何かを探しています。

EDIT 1つまたは複数のフィールド主キーの例として=
テーブル顧客は(たCompanyId、のCustomerName、住所、CREATEDATE)を有します。
Customersの主キーはCustomerNameがCustomerNameです。

私はまた、テーブルのものなどを処理するために知っている一般的なGetByIdを探しています。

+0

あなたは何をしたいかの例を挙げることができますか? 「1つまたは複数のフィールドを主キーとしてどのように持つことができますか?複合キーを意味しますか? – svick

+0

@svick:例を追加しました。 – Naor

+0

概念的には、正しいオーバーロードを選択したときにコンパイラが実行する必要があるのと同じですか? –

答えて

0

私はあなたが適切なキーフィールドで各渡された値の間に参加することはできませんので、あなたがそのようなものを実装することはできませんと思います。

私は、エンティティごとにカスタムメソッドを使用してお勧めしたい:CodeNameを想定すると、

Personテーブル内のキーです:

public IEnumerable<Person> ReadById(int code, string name) 
{ 
    using (var entities = new Entities()) 
     return entities.Persons.Where(p => p.Code = code && p.Name = name); 
} 
+0

これは私が避けたいものです。それぞれのクラスGetByIdメソッドを記述します。 – Naor

+0

@Napr:私の心には一般的な方法はありませんが、あまりにも多くはないと思います。 – Homam

4

そうでない場合は、「一般的な」アプローチを得ることができませんどのくらい多くのメンバーがキーに属しているか、どのタイプに所属しているかを知る。私は、複数のキーにmy solution for single keyを変更し、それは一般的なではありませんあなたが見ることができるように - それはキーが定義されているため使用しています。私はそれが一般的なものであるため、これは可能だろうか役に立つかわからないが、あなたは何ができる

// Base repository class for entity with any complex key 
public abstract class RepositoryBase<TEntity> where TEntity : class 
{ 
    private readonly string _entitySetName; 
    private readonly string[] _keyNames; 

    protected ObjectContext Context { get; private set; } 
    protected ObjectSet<TEntity> ObjectSet { get; private set; } 

    protected RepositoryBase(ObjectContext context) 
    { 
     if (context == null) 
     { 
      throw new ArgumentNullException("context"); 
     } 

     Context = context; 
     ObjectSet = context.CreateObjectSet<TEntity>(); 

     // Get entity set for current entity type 
     var entitySet = ObjectSet.EntitySet; 
     // Build full name of entity set for current entity type 
     _entitySetName = context.DefaultContainerName + "." + entitySet.Name; 
     // Get name of the entity's key properties 
     _keyNames = entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray(); 
    } 

    public virtual TEntity GetByKey(params object[] keys) 
    { 
     if (keys.Length != _keyNames.Length) 
     { 
      throw new ArgumentException("Invalid number of key members"); 
     } 

     // Merge key names and values by its order in array 
     var keyPairs = _keyNames.Zip(keys, (keyName, keyValue) => 
      new KeyValuePair<string, object>(keyName, keyValue)); 

     // Build entity key 
     var entityKey = new EntityKey(_entitySetName, keyPairs); 
     // Query first current state manager and if entity is not found query database!!! 
     return (TEntity)Context.GetObjectByKey(entityKey); 
    } 

    // Rest of repository implementation 
} 
+0

@Ladislav Mrnka:なぜリポジトリを抽象としてマークしましたか? – Naor

+0

@Ladislav Mrnka:あなたのソリューションとあなたのソリューションの違いは何ですか?http://stackoverflow.com/questions/5166297/generic-repository-ef4-ctp5-getbyid/5167709#5167709? – Naor

+1

@Naor:違いはEFのバージョンです。これはObjectContext APIとEFv4のためのもので、リンクされたAPIはDbContext APIとEFv4.1用です –

2

をこの:

public TEntity GetById<TEntity>(params Expression<Func<TEntity, bool>>[] keys) where TEntity : class 
{ 
    if (keys == null) 
     return default(TEntity); 

    var table = context.CreateObjectSet<TEntity>(); 
    IQueryable<TEntity> query = null; 
    foreach (var item in keys) 
    { 
     if (query == null) 
      query = table.Where(item); 
     else 
      query = query.Where(item); 
    } 
    return query.FirstOrDefault(); 
} 

、その後、あなたはこのようにそれを呼び出すことができます。

var result = this.GetById<MyEntity>(a => a.EntityProperty1 == 2, a => a.EntityProperty2 == DateTime.Now); 

免責事項:これは本当に、GetByidではありません、それは「私はあなたにカップルのパラメータを与えてみましょう本当にだと私にマッチする最初のエンティティを与えてください "。しかし、それはジェネリックスを使用しており、一致するものがあればエンティティを返し、主キーに基づいて検索します。

+0

これはどこでやっているのと同じです。 – Naor

+0

@Naor、正確ではありませんが、 'IQueryable 'を返します。これは 'TEntity'を返すでしょう – Jose

+0

これはSingleと同じです:) – Naor

0

[OK]を、これはそれで私の第二の刺しあります。私はこれがあなたのために働くと思う。

public static class QueryExtensions 
{ 
    public static Customer GetByKey(this IQueryable<Customer> query, int customerId,string customerName) 
    { 
     return query.FirstOrDefault(a => a.CustomerId == customerId && a.CustomerName == customerName); 
    } 

} 

したがって、この拡張メソッドの背後にある美しさは、あなたが今、これを行うことができます:

Customer customer = Db.Customers.GetByKey(1,"myname"); 

あなたがそれを必要とする場合は、明らかに、すべてのタイプのためにこれをしなければならないが、それはおそらく価値がある:)

+0

ホセ、これはいい答えですが、もっとサポートする汎用的な方法を探していますプライマリキーとして1つのフィールド。あなたのバージョンでは、各クラスのメソッドを記述して、このメソッドを汎用的にすると、複数のフィールドがpkであるテーブルに問題が生じます。 – Naor

関連する問題