在线商店的实体订单具有成员 DeliveryDetails 。 DeliveryDetails 的目的是包含特定于用户选择的递送方法的数据(例如,运输或从商店取货),而某些细节对于所有方法都是通用的(例如,名字,姓氏,电话号码) 。我在考虑使用继承的类似于以下内容的结构:
public class Order {
// ....other props...
public DeliveryMethodType DeliveryMethodType { get; set; }
public DeliveryDetailsBase DeliveryDetails { get; set; }
}
public class DeliveryDetailsBase
{
public int Id { get; set; }
public string CustomerId { get; set; }
public Order Order { get; set; }
public int OrderId { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string PhoneNumber { get; set; }
}
public class DeliveryDetailsShipping : DeliveryDetailsBase
{
public string Street { get; set; }
public string Building { get; set; }
public string Appartment { get; set; }
public string PostalCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
public class DeliveryDetailsPickupFromStore : DeliveryDetailsBase
{
public string StoreCode { get; set; }
}
但是,我无法弄清楚如何根据客户选择的方法以及如何在ASP.Core上的EntityFramework中将 DeliveryDetails 道具分配给不同类型的交付方法详细信息。
我已经尝试过的解决方法:
->(1)。为所有传递方法创建“超级类”竞争道具,并仅在db中填充所选传递方法所需的那些(通过设置枚举 DeliveryMethodType 进行选择)。 OUTCOME :有效,但具有一张大而丑陋的表格,其中包含多个null。
->(2)。在订单中,创建道具 DeliveryDetails ,该道具又包含 DeliveryDetailsPickupFromStoreDATA 和 DeliveryDetailsShippingDATA 。 OUTCOME :可以工作,但是有几个相关的表,并且有很多丑陋的代码检查枚举中的选定类型,为选定的传递方法实例化特定的子类,并将其他未使用的子类设置为空。
总结:还有其他更优雅,更可行的方法来组织此活动吗?
答案 0 :(得分:0)
EF Core仅实现了Table Per Hierarchy (TPH)继承。
每种类型的表(TPT)为still an open ticket(未实现)。
每个具体类型(TPC)的表格也为still an open ticket(未实现)。
因此,如果TPH满足您的要求,则可以follow this guide。
基本上,将使用一个表,并使用名为Discriminator
的额外列来确定记录对应的实现。
如果您刚开始使用Entity,我的建议是不要使用继承,而应将可空列用于根据类型而可能需要或不需要的数据。
答案 1 :(得分:0)
“还有其他更优雅,更可行的方式来组织这一活动吗?”保持简单,继承通常并不简单。 :)
一般而言,我选择继承而不是继承。使用起来更容易。给定需要传递到地址或商店的订单:
public class Order
{
public DeliveryMethod DeliveryMethod { get; set; } = DeliveryMethod.None;
public virtual OrderDeliveryAddress { get; set; } // should never be null.
public virtual OrderDeliveryStore { get; set; } // not null if delivery mode = store.
}
public class Address
{
public string Street { get; set; }
public string Building { get; set; }
public string Appartment { get; set; }
public string PostalCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
public class OrderDeliveryAddress
{
public virtual Order Order { get; set; }
public virtual Address Address { get; set; }
}
public class Store
{
public int StoreId { get; set; }
public virtual Address { get; set; }
}
public class OrderDeliveryStore
{
public virtual Order Order { get; set; }
public virtual Store Store { get; set; }
}
其中DeliveryMethod是枚举。 {None = 0,ToAddress,ToStore}
下订单后,操作员可以选择将其交付到某个地址,选择客户的地址或输入新的地址记录;或者他们可以将其传递到商店,也可以将OrderDeliveryAddress设置为商店的地址。您可以在数据库/系统中建立检查,以确保交付方法和引用的OrderDeliveryAddress / OrderDeliveryStore的数据完整性同步,并引发可能出现的不匹配情况。
一个考虑因素是,在交付时,您可能希望根据客户地址克隆一个新的地址记录,或在订购时存储适用的地址,而不是通过ID引用其当前地址记录。原因是出于历史完整性。订单将在该时间点被发送到该地址,并且如果将来客户地址或商店地址发生更改,则过去的订单仍应显示该订单已交付的地址。