【问题标题】:LINQ .Include() properties from sub-types in TPH inheritanceTPH 继承中子类型的 LINQ .Include() 属性
【发布时间】:2015-02-21 18:55:57
【问题描述】:

我在实体框架中使用逐层表 (TPH) 继承。现在我正在寻找一个列表——在这个例子中——部门可以是一个子类型。我希望集合中的项目包含它们自己的自定义属性,而不仅仅是基本模型的属性。

我怎样才能做到这一点?

public class Department
{
    public Department()
    {
        DepartmentType = this.GetType.Name;
    }
    public int Id {get; set;}
    public string DepartmentType {get; set;}
}

public class Finance : Department
{
    public virtual Manager Manager {get; set;}
}

public class Sports : Department
{
    public virtual Coach Coach {get; set;}
}


// This obviously crashes instantly
// How can I include Manager if type is Finance and Coach if type is Sports?
context.Departments
        .Include(c => (c is Finance) ? c.Manager : null)
        .Include(c => (c is Sports) ? c.Coach : null);

我什至尝试返回 IEnumerable<object> 并为每个子类型添加一个多态方法,如下所示:

public class Sports : Department
{
    public Coach Coach {get; set;}

    public object Export()
    {
        return new 
        {
            this.Id,
            this.DepartmentType,
            this.Coach
        }
    }
}

然后做这样的事情:

context.Departments.Select(c => c.Export())

但这也不起作用。

所需的 JSON 用法

[
    { Id: 1, DepartmentType: "Finance", Manager: { Name: "John" } },
    { Id: 2, DepartmentType: "Finance", Manager: { Name: "Harold" } },
    { Id: 3, DepartmentType: "Sport", Coach: { Name: "Fred", SportType: "Soccer" } },
    { Id: 4, DepartmentType: "Finance", Manager: { Name: "Hank" } },
    { Id: 5, DepartmentType: "Sport", Coach: { Name: "Mark", SportType: "Football" } }
]

【问题讨论】:

  • 您希望只能自动导出还是需要导入?
  • 它纯粹是为了在 Angular 前端中显示
  • 然后而不是 public object Export() 创建一个 public string NicePrint() 或重载 ToString()
  • 主要问题是子类型导航属性没有急切加载,我只得到基本类型属性
  • 这个链接可以帮到你:weblogs.asp.net/manavi/…

标签: c# json linq inheritance


【解决方案1】:

通过这种方式,您可以找到财务和体育部门并包含他们的属性:

var financeDeparments = context.Departments.OfType<Finance>().Include(p => p.Manager).ToList();
var sportDepartments = context.Departments.OfType<Sports>().Include(p => p.Coach).ToList();

【讨论】:

    【解决方案2】:

    一种将所有部门放在一个可以序列化为 JSON 的列表中的方法是

    var deparments = context.Departments.OfType<Finance>().Include(p => p.Manager)
                     .AsEnumerable()
                     .OfType<Department>()
                     .Union(
                     context.Departments.OfType<Sports>().Include(p => p.Coach)
                     ).ToList();
    

    解释:

    1. OfType&lt;Department&gt;():你不能直接Union 两个列表。您必须将其中一个投射到 IEnumerable&lt;Department&gt; 才能投射到另一个 Union。但是……

    2. .AsEnumerable():如果你只做演员表,EF 会断定它正在处理Depeartments,它不会接受Manager 的Include。通过包含AsEnumerble,您可以在内存中进行后续转换,而 EF 永远不会知道它。

    我认为这是一堆人为的代码,只是为了序列化。

    一个完全不同的选项是确保在上下文处于活动状态时进行序列化,因此触发延迟加载以填充导航属性。在这种情况下,您可以简单地序列化Departments,您将在 JSON 中找到派生类型的所有属性。也许(如果实际模型比您展示的更复杂)您必须防止循环引用。
    如果Department 的数量不太大,我认为这是一个可行的选择,即使它会为延迟加载生成大量查询。

    【讨论】:

    • 我现在无法对此进行测试(如果我在圣诞节开始编码,我的女朋友不会喜欢它),但 Union 方法看起来真的很有趣!如果这行得通,我会告诉你的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 2015-08-11
    • 1970-01-01
    • 2016-11-11
    相关资源
    最近更新 更多