C# 如何在Entity Framework 6中动态加载子实体

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

我有一个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 (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