在EF Core中维护派生类型中的关系

时间:2019-03-20 05:26:11

标签: c# asp.net-core ef-core-2.1 ef-core-2.2 entity-framework-core-2.1

我在维护派生类型中的关系并使用LINQ查询它们时遇到了一些问题。请考虑以下情形。假设我具有以下层次结构:

public class Company
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public abstract class Document
{
    public int Id { get; set; }
    public string DocType { get; set; }
    public string Name { get; set; }
}

public class CompanyDoc : Document
{
    public int CompanyId { get; set; }
    public Company Company { get; set; }
}

public class PersonDoc : Document
{
    public int PersonId { get; set; }
    public Person Person { get; set; }
}

这意味着我有一个文档对象,并且文档的所有者可以是任何公司或任何人,因此我创建了2个派生文档公司doc和person doc。

我的问题是,保持这种关系是否可以,如果没有,那么维持这种等级制度的最佳方法是什么?

在ef core 2.1中,我可以使用TPH处理此层次结构。但是,如果要与所有者一起获取所有文档,将是linq查询。我已经尝试过以下一种,但它不起作用。

var doc = (from d in _context.Set<Document>()
            join c in _context.Company on (d as CompanyDoc).CompanyId equals c.Id into cd
            from cdoc in cd.DefaultIfEmpty()
            join c in _context.Person on (d as PersonDoc).PersonId equals c.Id into pd
            from pdoc in pd.DefaultIfEmpty()
            select new {
                d.Id,
                d.Name,
                Owner = cdoc.Name != null ? cdoc.Name : pdoc.Name
            }).ToList()

您能通过分享您的想法来帮助我吗?请以这个为例。

1 个答案:

答案 0 :(得分:0)

我认为您使查询过于复杂。 EF Core非常聪明地处理每个层次结构表(TPH)查询。通过将抽象类用作DbSet<T>属性,您可以访问所有类型,并过滤出所需的内容。

因此,在您的示例中,DbContext将包含属性public DbSet<Document> Documents { get ; set; },以下查询将起作用。

//This returns all the documents - each document is of the correct type
//e.g PersonDocument or CompanyDocument
var allDocs = context.Documents.ToList();

//This would only return PersonDocuments - change the type for other versions
var personDocs = context.Documents.OfType<PersonDocument>().ToList();

EF Core会尽一切努力为您获取正确的数据和类型。很好用。

PS。如果您有我的书,请参阅TPH上的第7.8.2节,尤其是第201页。