Find a specified generic DbSet in a DbContext dynamically when I have an entity

c# code-first dbset entity-framework generics

Question

I have following classes and 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; }
    ....
}   

I have a list of objects that want to add to my context, too, but I don't know how can I find appropriate generic DbSet according each entity type dynamically.

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);         
}

How can I do that?

1
30
8/20/2016 3:31:39 AM

Accepted Answer

DbContext has a method called Set, that you can use to get a non-generic DbSet, such as:

var someDbSet = this.Set(typeof(SomeEntity));

So in your case:

foreach (BaseEntity entity in list)
{
      cntx.Set(entity.GetType()).Add(entity);         
}
45
2/3/2014 5:31:23 PM

Popular Answer

The question does not specify EF version and the proposed answer does not work anymore for Entity Framework Core (in EF Core, DbContext does not have a non-generic Set method, at least at the date of this answer).

Yet you can still have a working extension method using Jon Skeet's answer to this question. My code is added below for convenience.

Update: Added the generic function call as well returning IQueryable<T> thanks to the comment from 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>;
} 


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow