web-dev-qa-db-ja.com

EntityFramework IDでオブジェクトを取得しますか?

Genericsでは、タイプを知らなくてもEntityFrameworkからオブジェクトを取得できますか?

私は線に沿って何かを考えています:

_public T GetObjectByID<T>(int id)
{
   return (from i in myDatabase.T where i.ID == id select i);
}
_

それはできますか? Reflectionを使用して、何らかの形でT.GetType().Nameを取得し、テーブルに使用できますか?

[〜#〜] edit [〜#〜]
別の問題として、利用可能なすべてのテーブルが一意の列名として「ID」を使用しているわけではありません。

25
James P. Wright

最後にこれで問題を解決しました:
http://Pastebin.com/kjXUKBNS

コードを呼び出すには、これを使用します:

// Get the id of the object we are saving
PropertyInfo prop = GetProperty<TEntity>(entity, entity.EntityKey.EntityKeyValues[0].Key);
string entityID = prop.GetValue(entity, null).ToString();

// Get the current version of this object
var originalEntity = GetEntity<TEntity>(PropertyEquals, entityID);

これは、検索する主キーが主キーのリストの最初のキーであると仮定しています。

3
James P. Wright

すべてのエンティティによって実装されるインターフェースを定義できます:

public interface IEntity
{
    int Id { get; }
}

エンティティを取得するメソッド:

public T GetObjectById<T>(int id) where T : class, IEntity
{
    return context.CreateObjectSet<T>().SingleOrDefault(e => e.Id == id);
}

リンクされた質問 で提供されているアプローチと同様のアプローチを使用することもできます。エンティティを取得するには、別のメソッドを使用するだけです。

public virtual T GetByKey<T>(int id) where T : class, IEntity
{
     string containerName = context.DefaultContainerName;
     string setName = context.CreateObjectSet<T>().EntitySet.Name;
     // Build entity key
     var entityKey = new EntityKey(containerName + "." + setName, "Id", id);
     return (TEntity)Context.GetObjectByKey(entityKey);         
}

違いは、インスタンスを既にコンテキストにロードしている場合でも、最初のメソッドは常にデータベースを照会するのに対して、2番目のアプローチはインスタンスがすでにロードされているかどうかを最初にチェックすることです。このメソッドは、これらの名前を何度も作成するため、それほど効率的ではありません。 Here は、任意のキーの種類と名前で機能するより一般的なアプローチです。 here は、複雑なキーで機能するアプローチです。

このメソッドはどちらも継承を直接使用できません。ベースタイプを指定して機能させる必要があります。

31
Ladislav Mrnka

Find()メソッドは、あなたが探していることを実行できるかもしれないと思います( DbSet.Find Method )。

var someEntity = dbSet.Find(keyValue);
27
Yuck

エンティティは複合キーを持つことができるため、完全に汎用的なソリューションを作成することは困難ですが、これは単純な単一キーの場合には機能します。

キーは、T型をSystem.Data.Objects.DataClasses.EntityObject型に制限し、EntityKeyプロパティ(主キーを表す)として使用することです。

static T GetById<T>(object id) where T : EntityObject
{
    using (var context = new MyEntities())
    {
        return context.CreateObjectSet<T>()
            .SingleOrDefault(t => t.EntityKey.EntityKeyValues[0].Value == id);
    }
}
5
Kirk Broadhurst

エンティティフレームワークのIDからエンティティを取得する別の方法

public T Get<T>(int id) where T : EntityObject;
{
var ObjectSet = _context.CreateObjectSet<T>();
var PropName = ObjectSet.EntitySet.ElementType.KeyMembers[0].ToString();
return  ObjectSet.Where("it." + PropName + "=" + id).FirstOrDefault();
}

結果

SELECT TOP (1) 
[Extent1].[CatId] AS [CatId], 
[Extent1].[CatName] AS [CatName], 
[Extent1].[CatType] AS [CatType],  
FROM [dbo].[Categories] AS [Extent1]
WHERE [Extent1].[CatId] = 1
3

これが役立つと思う

public static TEntity Find<TEntity>(this ObjectSet<TEntity> set, object id) where TEntity : EntityObject
    {
      using (var context = new MyObjectContext())
      {
        var entity = set.Context.CreateObjectSet<TEntity>();
        string keyName = entity.FirstOrDefault().EntityKey.EntityKeyValues.FirstOrDefault().Key;

        return entity.Where("it." + keyName + " = " + id).FirstOrDefault();
      }
    }
2
Mustafa Magdy

私がやったことの1つは、「KeyComparator」インターフェースを定義することです:

public interface IHasKeyComparator<TObject> {
   Expression<Func<TObject, bool>> KeyComparator { get; } 
}

そして、複数の値を持つキーを使用しても、オブジェクトに実装できます。

public sealed class MultiKeyedObject : IHasKeyComparator<MultiKeyedObject> {
   public int ID1 { get; set; }
   public string ID2 { get; set; }       

   readonly Expression<Func<MultiKeyedObject, bool>> mKeyComparator;

   public Expression<Func<MultiKeyedObject, bool>> KeyComparator {
      get { return mKeyComparator; }
   }

   public MultiKeyedObject() {
      mKeyComparator = other => other.ID1 == ID1 && other.ID2 == ID2;
   }
}

制約を指定すると、一般的に使用できます。

public TObject Refresh<TObject>(TObject pObject)
where TObject : IHasKeyComparator<TObject> {
   return this.Set<TObject>().Single(pObject.KeyComparator);
}

ただし、この方法で行うには、オブジェクトのインスタンスが必要です。ただし、空のインスタンスにキー値を入力し、それを使用してDBからプルすることができます。

0
Dave Cousineau