Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have following classes and DbContext:

public class Order : BaseEntity {     public Number {get; set;} } public class 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?

like image 261
Masoud Avatar asked Feb 03 '14 17:02

Masoud


People also ask

Is DbSet part of DbContext?

Definition. A DbSet represents the collection of all entities in the context, or that can be queried from the database, of a given type. DbSet objects are created from a DbContext using the DbContext.

What is the use of DbContext class?

Definition. A DbContext instance represents a combination of the Unit Of Work and Repository patterns such that it can be used to query from a database and group together changes that will then be written back to the store as a unit.

What is the difference between DbSet and DbContext?

Intuitively, a DbContext corresponds to your database (or a collection of tables and views in your database) whereas a DbSet corresponds to a table or view in your database. So it makes perfect sense that you will get a combination of both!


Video Answer


2 Answers

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);          } 
like image 81
Pablo Romeo Avatar answered Sep 28 '22 21:09

Pablo Romeo


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>; }  
like image 43
user3141326 Avatar answered Sep 28 '22 19:09

user3141326