次のクラスとDbContext
があります。
public class Order:BaseEntity
{
public Number {get; set;}
}
Product:BaseEntity;
{
public Name {get; set;}
}
public class Context : DbContext
{
....
public DbSet<Order> Orders { set; get; }
public DbSet<Product> Products { set; get; }
....
}
コンテキストに追加したいオブジェクトのリストもありますが、各エンティティタイプに応じて適切なジェネリックDbSet
を動的に見つける方法がわかりません。
IList<BaseEntity> list = new List<BaseEntity>();
Order o1 = new Order();
o1.Numner = "Ord1";
list.Add(o1);
Product p1 = new Product();
p1.Name = "Pencil";
list.Add(p1);
Context cntx = new Context();
foreach (BaseEntity entity in list)
{
cntx.Set<?>().Add(entity);
}
どうやってやるの?
DbContext
にはSet
というメソッドがあり、これを使用して、次のような非汎用DbSet
を取得できます。
var someDbSet = this.Set(typeof(SomeEntity));
あなたの場合:
foreach (BaseEntity entity in list)
{
cntx.Set(entity.GetType()).Add(entity);
}
質問はEFバージョンを指定しておらず、提案された回答はEntity Frameworkコアでは機能しません(少なくともこの回答の日付では、DbContextのEFコアには非ジェネリックセットメソッドがありません)。
それでも、 この質問 に対するJon Skeetの回答を使用して、有効な拡張メソッドを使用できます。便宜上、以下に私のコードを追加します。
**更新:ジェネリック関数呼び出しを追加し、ShaddixからのコメントのおかげでIQueryable <T>を返すようにしました。
public static IQueryable Set(this DbContext context, Type T)
{
// Get the generic type definition
MethodInfo method = typeof(DbContext).GetMethod(nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance);
// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(T);
return method.Invoke(context, null) as IQueryable;
}
public static IQueryable<T> Set<T>(this DbContext context)
{
// Get the generic type definition
MethodInfo method = typeof(DbContext).GetMethod(nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance);
// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeof(T));
return method.Invoke(context, null) as IQueryable<T>;
}
パブロの答えに加えて:
プロジェクトにクラスを追加できます。
namespace System.Data.Entity
{
public static class EntityFrameworkExtensions
{
public static IEnumerable<object> AsEnumerable(this DbSet set)
{
foreach (var entity in set)
yield return entity;
}
}
}
このクラスは、拡張メソッドAsEnumerable
をDbSet
インスタンスに追加し、たとえばCountまたはfilter some rowの場合に使用します。
var someDbSet = this.Set(typeof(SomeEntity));
var count = (from a in someDbSet.AsEnumerable() select a).Count();