TPH 继承中子类型的 LINQ .Include() 属性

问题描述 投票:0回答:3

我在实体框架中使用每层次结构表 (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" } }
]
c# json linq inheritance
3个回答
1
投票

通过这种方式你可以找到财务和体育部门并包括他们的财产:

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

1
投票

将所有部门放入一个可以序列化为 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<Department>()
    :您不能直接
    Union
    两个列表。您必须将其中一个投射到
    IEnumerable<Department>
    才能将另一个投射到
    Union
    。但是...

  2. .AsEnumerable()
    :如果您只进行强制转换,EF 将断定它正在处理
    Depeartment
    ,并且不会接受
    Include
    Manager
    。通过包含
    AsEnumerble
    ,您可以在内存中执行后续转换,而 EF 永远不会知道它。

我认为这是一堆仅为了序列化而设计的代码。

一个完全不同的选项是确保在上下文处于活动状态时进行序列化,因此会触发延迟加载来填充导航属性。在这种情况下,您可以简单地序列化

Department
,然后您将在 JSON 中找到派生类型的所有属性。也许(如果实际模型比您显示的更复杂)您必须防止循环引用。
如果
Department
的数量不太大,我认为这是一个可行的选择,尽管它会生成大量延迟加载的查询。


0
投票

这对我有用。 创建与

相同的结果类
public class DepartmentQueryResult

{ 公开列出部门{ get; }

public DepartmentQueryResult()
{
    Departments= new List<Department>();
}

public int Add(Department department)
{

    if (type(department) == Finance )
        Departments.Add((Finance)department);
    else
         Departments.Add((Sports )department);
    
    return  Departments. Count;
}

编写您的 LINQ 查询

var queryResult =new List<Department>();
    
     DbSet.Where(specification)                          
          .Select(p=>queryResult.Add(p))
          .ToList();

您可以将queryResult序列化为JSON

© www.soinside.com 2019 - 2024. All rights reserved.