LINQ .INCLUDE()从子类型TPH继承性 [英] LINQ .Include() properties from sub-types in TPH inheritance

查看:125
本文介绍了LINQ .INCLUDE()从子类型TPH继承性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用实体框架表每层次(TPH)继承。现在,我希望得到的名单 - 在这个例子 - 在哪里部门的部门可以是子类型。我希望集合中的项目包括自己的自定义属性并不仅是基础模型的属性。



我怎样才能做到这一点?

 公共类系
{
公共部门()
{
DepartmentType = this.GetType.Name;
}
公众诠释标识{搞定;设置;}
公共字符串DepartmentType {搞定;设置;}
}

公共类金融:系
{
公共虚拟经理经理{搞定;设置;}
}

公共类体育:系
{
公共虚拟教练教练{搞定;设置;}
}


//这显然崩溃瞬间
//我怎么能包括经理,如果类型是财务和教练,如果类型是体育?
context.Departments
.INCLUDE(C =>(c是财务)c.Manager:空)
.INCLUDE(C =>(c是体育)c.Coach? : 空值);



我甚至试图返回的IEnumerable<对象> 并添加一个多态的方法每个子类型是这样的:

 公共类体育:系
{
公众教练教练{搞定;设置;}

公共对象导出()
{
返回新的
{
this.Id,
this.DepartmentType,
this.Coach
}
}
}

和然后做这样的事情:

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

但是,这并不工作。



所需JSON用法



  [
{ID:1,DepartmentType:财经,经理:{名称:约翰} }
{ID:2,DepartmentType:财经,经理:{名称:哈罗德}},
{ID:3,DepartmentType:运动,教练:{名称:弗雷德SportType:足球}},
{ID:4,DepartmentType:财经,经理:{名称:汉克}},
{ID:5,DepartmentType:运动 ,教练:{名称:马克,SportType:足球}}
]


解决方案

要获得一个列表中的所有部门可序列化到JSON的方法是

  VAR部门工作人员= context.Departments.OfType<融资方式>()包括(p => p.Manager)
.AsEnumerable()
.OfType<系>()
.Union(
context.Departments.OfType<体育GT;()。包括(P => ; p.Coach)
).ToList();



说明:




  1. OfType<系>():你不能联盟这两个列表直接。你必须投其中一人的IEnumerable<系> 要能够联盟其它。但是......


  2. .AsEnumerable():如果你只能做演员,EF将结束它在处理 Depeartment S,也不会接受包含中的管理。通过包括 AsEnumerble 你做后续投在内存和EF永远不知道它。




我觉得这是一个相当一堆只为序列化的缘故做作代码。



一个完全不同的选择是确保序列化时发生背景是活的,所以延迟加载触发填充导航属性。在这种情况下,你可以简单地连载和你会发现在JSON派生类型的所有属性。也许(如果实际模型比大家展示一下更复杂的),你必须避免循环引用。结果
。如果的数量不会太大我认为这是一个可行的选择,即使它会产生一些对延迟加载查询。


I am using table-per-hierarchy (TPH) inheritance in Entity Framework. Now I am looking to get a list of - in this example - Departments where departments can be a sub-type. I'd like the items in the collection to include their own custom properties and not only the Base Model's properties.

How can I achieve this?

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);

I have even tried to return IEnumerable<object> and add a polymorphic method to each sub-type that looked like this:

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

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

and then do something like this:

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

But that doesn't work either.

Desired JSON Usage

[
    { 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" } }
]

解决方案

A way to get all departments in one list that can be serialized into JSON is

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

Explanation:

  1. OfType<Department>(): You can't Union both lists directly. You have to cast one of them to IEnumerable<Department> to be able to Union the other. But...

  2. .AsEnumerable(): If you only do the cast, EF will conclude it's dealing with Depeartments, and it won't accept the Include of the Manager. By including AsEnumerble you do the subsequent cast in memory and EF never knows about it.

I think this is quite a bunch of contrived code only for sake of serializing.

A totally different option is to make sure the serializing occurs while the context is alive, so lazy loading is triggered to populate the navigation properties. In that case, you could simply serialize Departments and you'll find all properties of derived types in the JSON. Maybe (if the actual model is more complex than what you show) you have to prevent circular references.
If the number of Department is not too large I think this is a viable option, even though it will generate a number of queries for lazy loading.

这篇关于LINQ .INCLUDE()从子类型TPH继承性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆