Entity Framework 仅父子 Table return 直系子
Entity Framework Parent Child Table return immediate children only
我有一个标准的父/子 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; }
}
我通过 WebApi 将其作为 REST api 公开,目前它将 return 当我如下获取节点时完整的父子层次结构。
{
"Id": 1,
"Name": "root",
"SegmentKey": null,
"ParentId": null,
"Children": [{
"Id": 2,
"Name": "Demographics",
"SegmentKey": null,
"ParentId": 1,
"Children": [{
"Id": 3,
"Name": "Gender",
"ParentId": 2,
"Children": []
}, {
"Id": 4,
"Name": "Age",
"ParentId": 2,
"Children": []
}, {
"Id": 5,
"Name": "Income",
"ParentId": 2,
"Children": []
}]
}, {
"Id": 6,
"Name": "Activity",
"SegmentKey": null,
"ParentId": 1,
"Children": [{
"Id": 7,
"Name": "Navigation",
"SegmentKey": null,
"ParentId": 6,
"Children": []
}, {
"Id": 8,
"Name": "Behaviour",
"SegmentKey": null,
"ParentId": 6,
"Children": []
}]
}]
}
但是,我只需要获取请求的对象和直接子对象 returned,这样我的消费者就可以在用户浏览数据时建立视觉表示。
更新:感谢大家的评论,一切看起来都很好,但我正在努力处理 .Include,因为我在一个异步方法中,在该方法中找到 returns 对象,我丢失了语境。即
[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);
}
如有任何帮助,我们将不胜感激
如果您不想检索 hole Children 列表,请删除 virtual 关键字。
并独立编写一个函数来加载第一个Child。
对您来说,这是因为您的实体中使用了 "virtual" 关键字。此关键字为您的集合启用延迟加载,因此当序列化程序开始序列化您的 children 集合时,它会尝试枚举此集合,从而导致它从数据库中加载。之后,这个集合中的每个元素被递归序列化,导致每个 children 集合从数据库加载负载(有 N+1 select 问题)。
做你想做的你需要:
首先,从您的 Children 属性 中删除 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; }
}
其次,您需要急切地将此集合加载到您的控制器中。此代码将只为您的 dataDictionary class 实例加载 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);
}
不要忘记在文件开头添加 using System.Data.Entity
以访问 .Include()
功能。
此外,请考虑在您的 api 中不使用 Entity Framework 实体 - 更好地创建 DTO,这将使您对数据库结构的依赖性降低 API - API 将只有 EF 实体的字段子集。您还可以在此处限制树的深度,使 child class 没有 Children 集合。
希望对您有所帮助!
我有一个标准的父/子 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; }
}
我通过 WebApi 将其作为 REST api 公开,目前它将 return 当我如下获取节点时完整的父子层次结构。
{
"Id": 1,
"Name": "root",
"SegmentKey": null,
"ParentId": null,
"Children": [{
"Id": 2,
"Name": "Demographics",
"SegmentKey": null,
"ParentId": 1,
"Children": [{
"Id": 3,
"Name": "Gender",
"ParentId": 2,
"Children": []
}, {
"Id": 4,
"Name": "Age",
"ParentId": 2,
"Children": []
}, {
"Id": 5,
"Name": "Income",
"ParentId": 2,
"Children": []
}]
}, {
"Id": 6,
"Name": "Activity",
"SegmentKey": null,
"ParentId": 1,
"Children": [{
"Id": 7,
"Name": "Navigation",
"SegmentKey": null,
"ParentId": 6,
"Children": []
}, {
"Id": 8,
"Name": "Behaviour",
"SegmentKey": null,
"ParentId": 6,
"Children": []
}]
}]
}
但是,我只需要获取请求的对象和直接子对象 returned,这样我的消费者就可以在用户浏览数据时建立视觉表示。
更新:感谢大家的评论,一切看起来都很好,但我正在努力处理 .Include,因为我在一个异步方法中,在该方法中找到 returns 对象,我丢失了语境。即
[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);
}
如有任何帮助,我们将不胜感激
如果您不想检索 hole Children 列表,请删除 virtual 关键字。
并独立编写一个函数来加载第一个Child。
对您来说,这是因为您的实体中使用了 "virtual" 关键字。此关键字为您的集合启用延迟加载,因此当序列化程序开始序列化您的 children 集合时,它会尝试枚举此集合,从而导致它从数据库中加载。之后,这个集合中的每个元素被递归序列化,导致每个 children 集合从数据库加载负载(有 N+1 select 问题)。
做你想做的你需要:
首先,从您的 Children 属性 中删除 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; }
}
其次,您需要急切地将此集合加载到您的控制器中。此代码将只为您的 dataDictionary class 实例加载 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);
}
不要忘记在文件开头添加 using System.Data.Entity
以访问 .Include()
功能。
此外,请考虑在您的 api 中不使用 Entity Framework 实体 - 更好地创建 DTO,这将使您对数据库结构的依赖性降低 API - API 将只有 EF 实体的字段子集。您还可以在此处限制树的深度,使 child class 没有 Children 集合。
希望对您有所帮助!