J'ai les classes suivantes et 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; }
....
}
J'ai aussi une liste d'objets que je souhaite ajouter à mon contexte, mais je ne sais pas comment trouver le générique DbSet
approprié en fonction de chaque type d'entité de manière dynamique.
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);
}
Comment puis je faire ça?
DbContext
a une méthode appelée Set
que vous pouvez utiliser pour obtenir une DbSet
non générique, telle que:
var someDbSet = this.Set(typeof(SomeEntity));
Donc dans votre cas:
foreach (BaseEntity entity in list)
{
cntx.Set(entity.GetType()).Add(entity);
}
La question ne spécifie pas la version EF et la réponse proposée ne fonctionne plus pour Entity Framework Core (DbContext n'a pas de méthode d'ensemble non générique dans EF core au moins à la date de cette réponse).
Pourtant, vous pouvez toujours utiliser une méthode d'extension en utilisant la réponse de Jon Skeet à cette question . Mon code est ajouté ci-dessous pour plus de commodité.
** Mise à jour: Ajout de l'appel de fonction générique renvoyant également IQueryable <T> grâce au commentaire de Shaddix.
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>;
}
En plus de Pablo répondre:
Vous pouvez ajouter une classe à votre projet:
namespace System.Data.Entity
{
public static class EntityFrameworkExtensions
{
public static IEnumerable<object> AsEnumerable(this DbSet set)
{
foreach (var entity in set)
yield return entity;
}
}
}
Cette classe ajoute une méthode Extention AsEnumerable
à DbSet
et lorsque vous souhaitez l’utiliser par exemple pour Count ou filter une ligne:
var someDbSet = this.Set(typeof(SomeEntity));
var count = (from a in someDbSet.AsEnumerable() select a).Count();