Entity Framework继承

Entity Framework inheritance

SQL层数:

我有一个table

实体框架层:

我有以下规则:所有状态为空的报价都是未完成的报价,状态为真是已接受的报价,状态为假的是拒绝的报价。此外,部分字段仅用于杰出,部分 - 仅用于已接受等......我使用数据库优先方法,因此,我从数据库更新了 EF 模型并将 Offer 实体重命名为 OfferBase 并创建了 3 child 类:

它适用于 add/select entities/records。现在我想 "move" offer from outstanding 到 accept offer,所以,我需要设置 Status=true (from Status is null) 以进行适当的记录。但是Entity Framework怎么办呢?如果我尝试 select 未完成的报价作为接受报价,我得到一个空引用(并且清楚为什么)

// record with ID=1 exists, but State is null, so, EF can not find this record and offer will be null after the following string
var offer = (from i in _db.OfferBases.OfType<EFModels.OfferAccepted>() where i.ID == 1 select i).FirstOrDefault();

如果我尝试 select 作为 OfferBase 实体,我会收到以下错误:

Unable to cast object of type 'System.Data.Entity.DynamicProxies.OfferOutstanding_9DD3E4A5D716F158C6875FA0EDF5D0E52150A406416D4D641148F9AFE2B5A16A' to type 'VTS.EFModels.OfferAccepted'.

    var offerB = (from i in _db.OfferBases where i.ID == 1 select i).FirstOrDefault();
    var offer = (EFModels.OfferAccepted)offerB;

添加了关于架构的注释:

我有 3 种类型的报价实体。有:AcceptOffer、DeclineOffer 和 OutstandingOffer。

接受报价:

  • UserID
  • ContactID
  • Notes
  • FirstContactDate
  • LastContactDate
  • [... and 5-10 the unique fields...]

拒绝报价:

  • UserID
  • ContactID
  • Notes
  • [... and 5-10 the unique fields...]

优秀报价:

  • UserID
  • ContactID
  • FirstContactDate
  • LastContactDate
  • [... and 5-10 the unique fields...]

如何正确操作?当然,我可以 select 一条记录,从数据库中删除并添加具有适当状态值的新记录,但是如何正常进行?

对象一旦创建就无法更改其类型。您的对象模型似乎是错误的。 您要么删除未完成的报价并从中创建一个已接受的报价(看起来像您当前正在做的),但是您可能会在创建具有新身份的新对象时失去关系(您也可以在删除旧对象之前复制它们)。或者您想保留同一个对象并更改其状态。

如果您想保持相同的身份,请选择 composition over inheritance

您的代码可能如下所示:

public class Offer
{
  public int Id { get; set; }
  public virtual OfferState State { get; set }
}

public class OfferState
{
  public int OfferId { get; set; }
  public string Notes { get; set; }
}

public class AcceptedOfferState : OfferState
{
  public DateTimeOffset AcceptDate { get; set; }
}

public class DeclinedOfferState : OfferState
{
  public DateTimeOffset DeclinedDate { get; set; }
}

如果您仍想更改对象的类型并保持其身份,则可以使用存储过程;正如 Noam Ben-Ami(EF 的 PM 所有者)所述:Changing the type of an entity.

与其尝试将这些自定义 classes 添加到您的 entity framework 模型,不如将它们创建为普通的 c# classes,然后使用投影从 entity framework 生成 class 到您自己的 class 例如

var accepteOffers= from i in _db.Offers
                   where i.ID == 1 && i.Status == true
                   select new OfferAccepted { AcceptDate = i.AcceptDate, StartTime = i.StartTime /* map all releaveant fields here */};