我需要帮助让我的WebApi控制器工作。
我有3个这样的模型。
第一张表
public class MainTable{
public int MainTableID { get; set; }
... Other Fields
public ICollection<SubTable> SubTables { get; set; }
}
第二张表
public class SubTable{
public int SubTableID { get; set; }
... Other Fields
public int MainTableID { get; set; }
[ForeignKey("MainTableID ")]
[JsonIgnore]
public virtual MainTable MainTable{ get; set; }
public ICollection<SubSubTable> SubSubTables { get; set; }
}
第三表
public class SubSubTable{
public int SubSubTableID { get; set; }
... Other Fields
public int SubTableID { get; set; }
[ForeignKey("SubTableID")]
[JsonIgnore]
public virtual SubTable SubTable{ get; set; }
}
由于此帖中未提及的其他关系,我需要展平第一个模型,所以我使用的是dto
DTO
public class TableDTO
{
public int MainTableID { get; set; }
... Other Fields (there is a lot of flattening happening here but I am going to skip it to keep this simple)
public ICollection<SubTable> SubTables { get; set; }
}
现在我把所有这些都排除在外了。对我的问题..我将这一切都链接到web api控制器。
如果我使用DTO并创建一个像这样的控制器
使用DTO的控制器
public IQueryable<TableDTO> GetMainTable()
{
var mainTable = from b in db.MainTables
.Include(b => b.SubTable.Select(e => e.SubSubTable))
select new TableDTO()
{
MainTableID = b.MainTableID
eager mapping of all the fields,
SubTables = b.SubTables
};
return mainTable;
}
这适用于除SubSubTable之外的所有返回null的内容。如果我抛弃DTO并创建一个像这样的控制器
没有DTO的控制器
public IQueryable<MainTable> GetMainTable()
{
return db.MainTables
.Include(c => c.SubTables)
.Include(c => c.SubTables.Select(b => b.SubSubTables));
}
这很完美,JSon会返回我需要的所有东西,除了我丢失了我急需代码的其他方面的DTO。我已经用我能想到的各种方式重写了我的代码,但没有任何作用。我很确定这可以通过DTO来完成,但我不知道它需要什么来使它工作,并且他们说“你不知道你不知道什么”所以希望有人在这里知道。
答案 0 :(得分:2)
在实体框架6(及更低版本)中,当查询在投影中结束时,始终会忽略Include
,因为Include
路径无法应用于最终结果。换句话说,Include
仅在可以定位at the very end of the LINQ statement时才有效。 (EF-core更通用)。
这对您没有帮助,因为您明确要返回DTO。实现此目的的一种方法是在将实体实现到内存后进行投影:
var mainTable = from b in db.MainTables
.Include(b => b.SubTable.Select(e => e.SubSubTable))
.AsEnumerable()
select new MessageDTO()
{
MainTableID = b.MainTableID ,
// eager mapping of all the fields,
SubTables = b.SubTables
};
短语“所有字段的热切映射”表明,无论如何,预测都不会缩小SELECT
子句的范围,因此它不会产生太大的影响。
另一种方法是将所有SubSubTable
个对象加载到您知道将从数据库中提取的MainTable
中的上下文中。 EF将通过 relationship fixup 填充所有SubTable.SubSubTables
个集合。
答案 1 :(得分:0)
如果有效:
public IQueryable<MainTable> GetMainTable()
{
return db.MainTables
.Include(c => c.SubTables)
.Include(c => c.SubTables.Select(b => b.SubSubTables));
}
然后使用此广告,只需在Select()
的末尾添加ToList()
。请注意返回类型中的IEnumerable
:
public IEnumerable<MainTableDto> GetMainTable()
{
return db.MainTables
.Include(c => c.SubTables)
.Include(c => c.SubTables.Select(b => b.SubSubTables))
.Select(c=> new MainTableDto { SubTables=c.SubTables /* map your properties here */ })
.ToList();
}
不确定类型(在一个地方MainTableDto
,另一个地方你提到MessageDto
?)。