Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架父子表仅返回直接子表_C#_Entity Framework_Rest_Asp.net Web Api2 - Fatal编程技术网

C# 实体框架父子表仅返回直接子表

C# 实体框架父子表仅返回直接子表,c#,entity-framework,rest,asp.net-web-api2,C#,Entity Framework,Rest,Asp.net Web Api2,我有一个标准的父/子EF模型,如下所示 public class DataDictionary { public int Id { get; set; } public String Name { get; set; } public int? ParentId { get; set; } [JsonIgnore] public virtual DataDictionary Parent { get; set; } public virtu

我有一个标准的父/子EF模型,如下所示

public class DataDictionary 
{
    public int Id { get; set; }
    public String Name { get; set; }

    public int? ParentId { get; set; }

    [JsonIgnore]
    public virtual DataDictionary Parent { get; set; }

    public virtual ICollection<DataDictionary> Children { get; set; }
}
但是,我只需要获取请求的对象和直接子对象,以便在用户浏览数据时,我的消费者可以建立可视化表示

更新:感谢大家的评论,所有这些看起来都很好,但是我正在努力解决。包括,因为我在一个异步方法中,查找返回了对象,而我丢失了上下文。i、 e

    [ResponseType(typeof(DataDictionary))]
    public async Task<IHttpActionResult> GetDataDictionary(int id)
    {
        DataDictionary dataDictionary = await db.DataDictionaries.FindAsync(id);
        if (dataDictionary == null)
        {
            return NotFound();
        }
        return Ok(dataDictionary);
    }
[ResponseType(typeof(DataDictionary))]
公共异步任务GetDataDictionary(int id)
{
DataDictionary DataDictionary=await db.DataDictionary.FindAsync(id);
if(dataDictionary==null)
{
返回NotFound();
}
返回Ok(数据字典);
}

如果您不想检索孔子列表,请删除virtual关键字,我们将非常感谢您的帮助


并独立编程一个函数来加载第一个子项。

对于您来说,这是因为实体中使用了“virtual”关键字。此关键字启用集合的延迟加载,所以当序列化程序序列化子集合时,它会尝试枚举此集合,从而导致从数据库加载它。之后,该集合中的每个元素都被递归序列化,从而导致从数据库加载每个子集合的负载(存在N+1选择问题)

要做你想做的事,你需要:

首先,从您的子属性中删除
virtual
关键字:

public class DataDictionary 
{
    public int Id { get; set; }
    public String Name { get; set; }

    public int? ParentId { get; set; }

    [JsonIgnore]
    public virtual DataDictionary Parent { get; set; }

    public ICollection<DataDictionary> Children { get; set; }
}
公共类数据字典
{
公共int Id{get;set;}
公共字符串名称{get;set;}
public int?ParentId{get;set;}
[JsonIgnore]
公共虚拟数据字典父项{get;set;}
公共ICollection子项{get;set;}
}
其次,您需要急切地将此集合加载到控制器中。此代码将导致仅为dataDictionary类实例加载1个级别:

[ResponseType(typeof(DataDictionary))]
public async Task<IHttpActionResult> GetDataDictionary(int id)
{
    DataDictionary dataDictionary = await db.DataDictionaries
        .Include(x=>x.Children)
        .FirstOrDefaultAsync(x=>x.Id == id);
    if (dataDictionary == null)
    {
        return NotFound();
    }
    return Ok(dataDictionary);
 }
[ResponseType(typeof(DataDictionary))]
公共异步任务GetDataDictionary(int id)
{
DataDictionary DataDictionary=等待db.DataDictionary
.包括(x=>x.儿童)
.FirstOrDefaultAsync(x=>x.Id==Id);
if(dataDictionary==null)
{
返回NotFound();
}
返回Ok(数据字典);
}
不要忘记在文件开头添加使用System.Data.Entity的
,以访问
.Include()
函数

也可以考虑,不要在API中使用实体框架实体——更好地创建DTOs,这将允许您对API结构有更少的依赖性,API -API只具有EF实体的一个子集字段。您还可以在这里限制树的深度,使子类没有子类集合


希望这有帮助

您可以禁用延迟加载,并仅对1个级别的子级执行快速加载。你能负担得起吗?是的,我能-我需要做什么才能触发仅1级的急切加载?我认为这样加载:
dbContext.DataDictionaries.Include(x=>x.Children)应该足够了,Include关键字是它被急切加载的原因。我认为现在当启用延迟加载时,序列化程序会遍历每个属性,导致lazy children集合的枚举,这会从DB中加载它们,并导致对每个孩子重复相同的过程,从而导致出现一个很好的旧N+1选择问题。感谢您的帮助-如Sergio所述,取消虚拟连接看起来不错,但是,我无法确定如何获得Include语句来填充子对象,因为我使用的是一个异步方法,该方法可以找到父对象,但我丢失了上下文。-请参阅更新的问题您能提供该方法的代码示例吗?谢谢Raderick-这正是我所需要的。同意你的紧耦合与松耦合的观点-我很懒:)很高兴这有帮助,@MarkRuse:)只是为了完整性,当我尝试上面的方法时,我从include链接得到了一个问题,因为它是可访问的,而不是DbSet(它有findAsync方法)。这解决了DataDictionary DataDictionary=await db.DataDictionary.Include(x=>x.Children.SingleOrDefaultAsync(i=>i.Id==Id)的问题@MarkRuse抱歉,我没有看到这一个,没有在ide中签入,你完全正确,我将相应地修改答案@MarkRuse还请记住,SingleOrDefault的效率可能低于FirstOrDefault,因为它会生成
SELECT TOP 2
查询,而不是像FirstOrDefault那样只选择一个匹配项。
[ResponseType(typeof(DataDictionary))]
public async Task<IHttpActionResult> GetDataDictionary(int id)
{
    DataDictionary dataDictionary = await db.DataDictionaries
        .Include(x=>x.Children)
        .FirstOrDefaultAsync(x=>x.Id == id);
    if (dataDictionary == null)
    {
        return NotFound();
    }
    return Ok(dataDictionary);
 }