EF gets a list of runtime entries from type

Purpose: I need to encode all records, for example:

var records = db.Set<UserAccount>().ToList(); 

Then cycle

 foreach (var record in records) { // do something with the record } 

But it doesnโ€™t have to specify a specific one at runtime, since I have to iterate over types and therefore do not know the example of "UserAccount". Only Type / TypeOf?

At the bottom of this description, I have a loopAllEntities method that I cannot find to work

I created a DbContext with some objects.

 public class MyEntities : DbContext { public DbSet<UserAccount> UserAccounts { get; set;} public DbSet<UserRole> UserRoles { get; set; } public DbSet<UserAccountRole> UserAccountRoles { get; set; } } 

The Type list for output control is defined:

 public static List<Type> ModelListSorted() { List<Type> modelListSorted = new List<Type>(); modelListSorted.Add(typeof(UserRole)); modelListSorted.Add(typeof(UserAccountRole)); modelListSorted.Add(typeof(UserAccount)); return modelListSorted; } 

The problem below is where I cannot find a way to do this. Work: - (

 public static loopAllEntities() { List<Type> modelListSorted = ModelHelper.ModelListSorted(); foreach (Type type in modelListSorted) { var records = ????? // get a list of records in the current table from type. foreach (var record in records) { // do something with the record } } } 
+5
source share
3 answers

It looks like you're almost there, you should do something like the following:

  public static void loopAllEntities(DbContext dbContext) { List<Type> modelListSorted = ModelHelper.ModelListSorted(); foreach (Type type in modelListSorted) { var records = dbContext.Set(type); // do something with the set here } } 

This will not give you a generic set of work. It depends on what you want to do, since there is no such type for this set that it can get a little confused, maybe thrown into the base type or interface to work with?

Edit: I do not have enough reputation for comment, but the Mayoors solution will allow you to get what you want without using a non-generic type and put together the entire collection.

+1
source

I initially thought that you cannot get entities only with type, but looking at Matt, you can. So this answer is probably not the best ...

The main idea is to get an IEnumerable<object> list, where each IEnumerable<object> is an entity in our model. The reason we should use the plain old object is because we want it to return different objects that are not related to each other. But this is not so bad, because when you scroll through each object, you can pass it to a specific object if you need to.

First we create a method that returns this list:

 private static List<IEnumerable<object>> AllEntities(MyEntities db) { List<IEnumerable<object>> list = new List<IEnumerable<object>>(); list.Add(db.UserRole); list.Add(db.UserAccountRole); list.Add(db.UserAccount); return list; } 

We go to our DbContext because it will be used when we actually start the loop through IEnumerables , which happens outside of this method. Therefore, we cannot create a DbContext here, and then Dispose it.

Now we can use this method to process all our objects:

 using (var db = GetMyEntities()) { List<IEnumerable<object>> recordsList = AllEntities(db); foreach (IEnumerable<object> records in recordsList) { foreach (object record in records) { // Do something with record. // If you need to access type-specific properties, // do something like below if (record is UserAccount) { UserAccount account = (UserAccount)record; Console.WriteLine("User Name: " + account.UserName); } } } } 

And it's all. In terms of SQL, it will do something like SELECT * FROM TABLE_NAME for each iteration of the foreach outer loop. This means that it does not cache the data inside List<IEnumerable<object>> , and every time you use AllEntities , it gets fresh data from the database.

+1
source

I know this is an old question, but the question does not indicate the version of EF, and the proposed answer no longer works for the Entity Framework Core (DbContext does not have a non-standard typing method in the EF core, at least for the date of this answer).

However, you can still use the working extension method using Jon Skeet's answer to this question . My code is added below for convenience.

  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; } 
0
source

Source: https://habr.com/ru/post/1205217/


All Articles