multiple - linq entity framework c#
Encontrar un DbSet genĂ©rico especificado en un DbContext dinĂ¡micamente cuando tengo una entidad (3)
Tengo las siguientes clases y 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; }
....
}
También tengo una lista de objetos que quiero agregar a mi contexto, pero no sé cómo puedo encontrar el DbSet
genérico DbSet
según cada tipo de entidad de forma dinámica.
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);
}
¿Cómo puedo hacer eso?
Además de la respuesta de Pablo:
Puedes agregar una clase a tu proyecto:
namespace System.Data.Entity
{
public static class EntityFrameworkExtensions
{
public static IEnumerable<object> AsEnumerable(this DbSet set)
{
foreach (var entity in set)
yield return entity;
}
}
}
Esta clase agrega un método de AsEnumerable
DbSet
instancia de DbSet
y cuando desea usarlo, por ejemplo, para contar o filtrar alguna fila:
var someDbSet = this.Set(typeof(SomeEntity));
var count = (from a in someDbSet.AsEnumerable() select a).Count();
La pregunta no especifica la versión de EF y la respuesta propuesta ya no funciona para Entity Framework Core (DbContext no tiene un método de conjunto no genérico en el núcleo de EF al menos en la fecha de esta respuesta).
Sin embargo, todavía puedes tener un método de extensión que funcione con la respuesta de Jon Skeet a esta pregunta . Mi código se agrega a continuación para mayor comodidad.
** Actualización: Se agregó la llamada a la función genérica y se devolvió IQueryable <T> gracias al comentario 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>;
}
DbContext
tiene un método llamado Set
, que puede usar para obtener un DbSet
no genérico, como:
var someDbSet = this.Set(typeof(SomeEntity));
Así que en tu caso:
foreach (BaseEntity entity in list)
{
cntx.Set(entity.GetType()).Add(entity);
}