C# 如何在Entity Framework 6中动态加载子实体
我有一个Provider类和一个Article类。文章有一个C# 如何在Entity Framework 6中动态加载子实体,c#,wpf,entity-framework,lazy-loading,eager-loading,C#,Wpf,Entity Framework,Lazy Loading,Eager Loading,我有一个Provider类和一个Article类。文章有一个int ProviderId{get;set}和一个公共虚拟提供程序Provider{get;set;}属性 我知道延迟加载以及为什么我不能在上下文之外访问文章中的Provider属性,但我有一个通用方法返回下一个t,如下所示: public static T Next<T>(T currentElement) where T : class, IModel { T data; if (currentEle
int ProviderId{get;set}
和一个公共虚拟提供程序Provider{get;set;}
属性
我知道延迟加载以及为什么我不能在上下文之外访问文章中的Provider属性,但我有一个通用方法返回下一个t,如下所示:
public static T Next<T>(T currentElement) where T : class, IModel {
T data;
if (currentElement.Id >= GetLastId<T>())
return currentElement;
using (DatabaseEntities context = new DatabaseEntities()) {
data = context.Set<T>().Single(el => el.Id == currentElement.Id + 1);
}
return data;
}
var someEntity = ...;
var nextEntity = Next(someEntity,
e => e.Childcollection1,
e => e.Childcollection2,
//
e => e.ChildcollectionN)
return query.OrderBy(el => el.Id).First(el => el.Id > currentElement.Id);
publicstatict Next(T currentElement),其中T:class,IModel{
T数据;
如果(currentElement.Id>=GetLastId())
返回电流元件;
使用(DatabaseEntities上下文=新DatabaseEntities()){
data=context.Set().Single(el=>el.Id==currentElement.Id+1);
}
返回数据;
}
但我无法在Articles类中检索像Provider这样的子实体。如何包含所有实体?我应该更新方法并为每个实体创建一个吗
我读过,但我不知道如何在我的方法中实现这些
注意:
var entity = Next(instance, x => x.Provider);
并非我的所有实体都有实体子实体,我有更多的方法,如
Previous()
、First()
或Last()
,可以完成您期望的工作。您可以扩展您的方法,以获取可能包含的列表。例如:
public static T Next<T>(T currentElement, params Expression<Func<T, object>>[] includes)
where T : class, IModel
{
if (currentElement.Id >= GetLastId<T>())
return currentElement;
using (DatabaseEntities context = new DatabaseEntities())
{
IQueryable<T> query = context.Set<T>();
//Deferred execution allows us to build up the query
foreach (var include in includes)
{
query = query.Include(include);
}
return query.Single(el => el.Id == currentElement.Id + 1);
}
}
另外一点是,要获取下一个实体,您不应该依赖于ID值是连续的,例如,如果删除条目,它们将失去顺序。取而代之的是,考虑这样的事情:
public static T Next<T>(T currentElement) where T : class, IModel {
T data;
if (currentElement.Id >= GetLastId<T>())
return currentElement;
using (DatabaseEntities context = new DatabaseEntities()) {
data = context.Set<T>().Single(el => el.Id == currentElement.Id + 1);
}
return data;
}
var someEntity = ...;
var nextEntity = Next(someEntity,
e => e.Childcollection1,
e => e.Childcollection2,
//
e => e.ChildcollectionN)
return query.OrderBy(el => el.Id).First(el => el.Id > currentElement.Id);
您可以为接受表达式的
下一个方法创建重载:
有关更多信息和完整示例,请参阅以下博客文章
使用实体框架实现通用数据访问层:因此在提供者
和文章
之间存在一对多关系:每个提供者
都有零个或多个文章
,而每个文章
都只属于一个提供者
如果您已在实体框架中正确配置了此一对多关系,则提供程序应具有对其多篇文章的引用:
public virtual ICollection<Article> Articles{get; set;}
我需要确保每个T都有一个Id,否则您无法获得下一个Id。可能您的IModel界面中有:
public Interface IId
{
public int Id {get;}
}
完成这些功能后,您的查询将如下所示:
public static T Next<T>(T currentElement) where T : class, IModel, IId
{
T data;
if (currentElement.Id >= GetLastId<T>())
return currentElement;
using (DatabaseEntities context = new DatabaseEntities())
{
return context.Set<T>().Next(currentElement);
}
}
公共静态T Next(T currentElement),其中T:class、IModel、IId
{
T数据;
如果(currentElement.Id>=GetLastId())
返回电流元件;
使用(DatabaseEntities上下文=新DatabaseEntities())
{
返回context.Set().Next(currentElement);
}
}
我不想重复回答,但这里有一个函数,它结合了一点反射,根据模型声明自动加载所有外键相关数据。我把它写为一种通过主键以外的东西加载对象的方法,但是如果需要的话可以修改它
private IQueryable<T> GetFullSet()
{
IEnumerable<IEntityType> entities = _dbContext.Model.GetEntityTypes();
IEntityType thisEntity = entities.SingleOrDefault(x => x.ClrType.Name == typeof(T).Name);
IQueryable<T> set = _dbContext.Set<T>();
foreach (IForeignKey fKey in thisEntity.GetReferencingForeignKeys())
{
set = set.Include(fKey.PrincipalToDependent.Name);
}
return set;
}
private IQueryable GetFullSet()
{
IEnumerable entities=_dbContext.Model.GetEntityTypes();
IEntityType thisEntity=entities.SingleOrDefault(x=>x.ClrType.Name==typeof(T.Name);
IQueryable集=_dbContext.set();
foreach(此实体中的IForeignKey fKey.getReferencengForeignKeys())
{
set=set.Include(fKey.PrincipalToDependent.Name);
}
返回集;
}
没有回答您的问题,但我认为使用Id+1
获取下一个元素可能很危险。如果删除表中的一行,它将引发异常。至于答案,您是否愿意将包含列表传递给此方法?@DavidG您的Id问题是对的,那么我是否应该将所有记录保存在列表中(可能是3000条)?但是这一次,我不能删除任何一行,是的,我可以使用includes。这正是我想要的相反。我的目标是在我得到文章时得到提供者,但如果我需要做相反的事情,我会看一看。谢谢你,我回家后会试试的。感谢您提供的代码片段,以获取下一个元素;)工作完美!谢谢:D