【问题标题】:Multiple Inheritance Levels in EF Code FirsEF Code First 中的多个继承级别
【发布时间】:2013-04-09 09:00:47
【问题描述】:

我试图弄清楚如何处理多种类型的继承。我有一个现有的 Code First / EF / MVC 项目,它在生产环境中具有实时数据。系统使用一种称为“文档”的类型,可以在该类型上执行许多功能,并且有许多关联表可以链接到 DocumentID。

目前有一种更加差异化的文档,即采购订单,它实现了一些更具体的属性,例如引用产品、数量和单价的“OrderLines”集合。还有一些特定于采购订单的其他字段。除了具有“OrderLines”与基本文档类型不同之外,采购订单是供应方文档,因此,它的第三方是“供应商”。将来可能还有其他供应方文件也将供应商作为第三方。

我现在准备实施一种新的文档类型,即需求方,这意味着它将有一个称为客户的第三方。它还有一个 OrderLines 集合。

我的系统目前设置为TPH,所以该表称为“文档”,并且有一个鉴别器列表示里面的文档是采购订单。

如何添加新类型并使用继承来实现 OrderLines 集合和 CustomerID / Customer 链接?看来c#不能做多重继承,所以下面的就不行了:

Document -> OrderLinesDocument -> PurchaseOrder

文档 -> OrderLinesDocument -> 发票

Document -> VendorDocument -> PurchaseOrder

文档 -> 客户文档 -> 发票

中产阶级会在哪里实现可能对许多文档但不是所有文档都通用的字段?

有没有办法使用接口来完成这个,并且仍然让 EF 正确地找出表格?

【问题讨论】:

标签: c# entity-framework asp.net-mvc-4


【解决方案1】:

继承在许多方面可能很棘手 - 所以我的建议是“轻松”地处理它。

但只要在这里做一个典型的 OO 设计就会产生可用的表和结构。也许这样的东西可以为你工作......

public class Document
{
    public long ID { get; set; }
    public string Name { get; set; }
}

public class OrderLinesDocument : Document
{
    public ICollection<OrderLine> OrderLines { get; set; }
}

public interface IVendorDocument
{
    ICollection<Vendor> Vendors { get; set; }
}
public class VendorDocument : Document, IVendorDocument
{
    public ICollection<Vendor> Vendors { get; set; }
}

public interface ICustomerDocument
{
    ICollection<Customer> Customers { get; set; }
}
public class CustomerDocument : Document
{
    public ICollection<Customer> Customers { get; set; }
}

public class PurchaseOrder : OrderLinesDocument, IVendorDocument
{
    public ICollection<Vendor> Vendors { get; set; }
}

public class Invoice : Document, ICustomerDocument
{
    public ICollection<Customer> Customers { get; set; }
}

IMO 最简单的解决方案是使用 TPH(几乎是“原样”)。

但正如我所说,小心使用它 - 它可能不适用于您的想法 - 即您需要进行试验,确保 Db 记录看起来最佳。

顺便说一句。如果你不知道,你可以这样使用它,忘记发布了......

var query1 = db.Documents.OfType<PurchaseOrder>().ToList();
var query2 = db.Documents.OfType<Invoice>().ToList();

var query3 = db.Documents.OfType<CustomerDocument>().ToList();
var query4 = db.Documents.OfType<VendorDocument>().ToList();
var query5 = db.Documents.OfType<OrderLinesDocument>().ToList();

var query6 = db.Documents.OfType<Document>().ToList();

(试试看它是如何工作的)

【讨论】:

  • 此解决方案是否适用于接口中的外键属性?它不是供应商的集合,而是公共虚拟供应商 Vendor {get; set;} 和 [ForeignKey("Vendor")] public int?供应商 ID {get;放;}。派生类上也有一些特定的功能。特定于每种文档类型的验证等。
  • 理想情况下它应该 - 接口在这里不是任何意义上的“侵入性” - “类”是(类影响表的创建方式) - 接口只为您提供相应的访问权限。所以你可以把你想要的所有接口都放进去,但问题是实现它的类。我不能告诉你,因为每种情况都不同,你总是可以打破它。这是一个测试布局。弄清楚细节,当你遇到麻烦时,再想想如何避免它。没有一般规则 - 但要注意“循环”路径、逻辑关系等。
  • 我还没有机会实现这个。对不起!完成后我会报告。
  • 还有一个问题——我如何访问视图中的不同类型?含义 如果我正在遍历引用文档的类型列表,然后显示该文档的属性,视图如何知道它是哪个子类型?就视图所知,每一个都是通用文档。我应该将这些投射到视图中吗?听起来不对,但我不知道还能做什么。
  • Type 告诉您它是哪个文档。您可以使用 is ... 甚至在 Document 中实现 enum DocType - 并覆盖每种文档类型 - 然后对其进行测试 - 然后您可以使用它“切换”。您拥有所需的所有信息。
猜你喜欢
  • 2012-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
相关资源
最近更新 更多