目的: 我需要循环所有记录,如:
var records = db.Set<UserAccount>().ToList();
然后循环
foreach (var record in records)
{
// do something with the record
}
但是它必须在运行时没有特定类型,因为我要遍历类型,因此不知道示例&#34; UserAccount&#34;。 只有Type / TypeOf?
在本说明的底部,我有一个方法 loopAllEntities ,我找不到工作方式
我用一些实体创建了一个DbContext。
public class MyEntities : DbContext
{
public DbSet<UserAccount> UserAccounts { get; set;}
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<UserAccountRole> UserAccountRoles { get; set; }
}
定义一个Type列表来控制输出:
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;
}
问题出现在我无法找到方法使其工作的地方: - (
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
}
}
}
答案 0 :(得分:1)
看起来你几乎就在那里,你应该可以做类似以下的事情:
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
}
}
这将为您提供一个非泛型集合。它取决于你想要做什么,因为这个集合没有类型它可能会有点棘手,可能会转换为基类型或接口来使用?
编辑:我没有足够的声誉来评论,但是Mayoors解决方案可以在不使用非泛型类型的情况下为您提供所需的内容,并且可以预先获得整个集合。
答案 1 :(得分:1)
我最初认为你不能只获得一种类型的实体,但是看看马特的答案,你可以。所以,这个答案可能并不是最好的答案......
基本想法是获取IEnumerable<object>
的列表,其中每个IEnumerable<object>
是我们模型中的实体。我们必须使用普通旧object
的原因是因为我们希望它返回彼此不相关的不同实体。但是,这并不是那么糟糕,因为当你循环遍历每个对象时,如果需要,可以将它转换为某个实体。
首先,我们将创建一个返回此列表的方法:
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;
}
我们传入DbContext
因为它会在我们实际开始循环遍历此方法之外的IEnumerables
时使用。因此,我们无法在此处DbContext
创建Dispose
。
我们现在可以使用此方法遍历所有实体:
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);
}
}
}
}
就是这样。就SQL而言,对于外部foreach循环的每次迭代,它将执行SELECT * FROM TABLE_NAME
之类的操作。这意味着它不会缓存List<IEnumerable<object>>
内的数据,每次使用AllEntities
时都会从数据库中获取新数据。
答案 2 :(得分:0)
我知道这是一个老问题,但问题并没有指定EF版本,并且提议的答案不再适用于Entity Framework Core(DbContext在EF核心中至少在日期时没有非通用的set方法)这个答案)。
然而,你仍然可以使用Jon Skeet的回答来this question。为方便起见,我的代码在下面添加。
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;
}