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?
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.
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.
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!
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); }
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>; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With