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」を使用しているわけではありません。
最後にこれで問題を解決しました:
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);
これは、検索する主キーが主キーのリストの最初のキーであると仮定しています。
すべてのエンティティによって実装されるインターフェースを定義できます:
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 は、複雑なキーで機能するアプローチです。
このメソッドはどちらも継承を直接使用できません。ベースタイプを指定して機能させる必要があります。
Find()
メソッドは、あなたが探していることを実行できるかもしれないと思います( DbSet.Find Method )。
var someEntity = dbSet.Find(keyValue);
エンティティは複合キーを持つことができるため、完全に汎用的なソリューションを作成することは困難ですが、これは単純な単一キーの場合には機能します。
キーは、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);
}
}
エンティティフレームワークの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
これが役立つと思う
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();
}
}
私がやったことの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からプルすることができます。