实体框架继承

时间:2015-03-10 17:42:31

标签: c# entity-framework inheritance

SQL图层:

我有一张桌子

enter image description here

实体框架层:

我有以下规则:所有优惠,其中State为null,是优惠优惠,State是真实的是Accepted offer,State is false是Declined offers。此外,部分字段仅用于Outstanding,part - 仅用于Accepted等...我使用Database first方法,因此,我从DB更新EF模型并将Offer实体重命名为OfferBase并创建了3个子类:

enter image description here

它适用于添加/选择实体/记录。现在我想要从优秀到接受报价“移动”报价,所以,我需要设置Status = true(从Status为null)以获得适当的记录。但是如何通过实体框架来实现呢?如果我尝试选择未完成的报价作为接受报价,我会得到一个空参考(明确原因)

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

如果我尝试选择OfferBase实体,我会收到以下错误:

  

无法投射类型的对象   'System.Data.Entity.DynamicProxies.OfferOutstanding_9DD3E4A5D716F158C6875FA0EDF5D0E52150A406416D4D641148F9AFE2B5A16A'   输入'VTS.EFModels.OfferAccepted'。

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

关于建筑的补充说明:

我有3种类型的Offer实体。有:AcceptOffer,DeclineOffer和OutstandingOffer。

AcceptOffer:

  
      
  • 用户ID
  •   
  • 的ContactID
  •   
  • 注释
  •   
  • FirstContactDate
  •   
  • LastContactDate
  •   
  • [...和5-10个独特的字段......]
  •   

DeclineOffer:

  
      
  • 用户ID
  •   
  • 的ContactID
  •   
  • 备注
  •   
  • [...和5-10个独特的字段......]
  •   

OutstandingOffer:

  
      
  • 用户ID
  •   
  • 的ContactID
  •   
  • FirstContactDate
  •   
  • LastContactDate
  •   
  • [...和5-10个独特的字段......]
  •   

如何正确完成?当然,我可以选择一条记录,从DB中删除并添加具有适当状态值的新记录,但是如何正常执行呢?

2 个答案:

答案 0 :(得分:6)

创建对象后,无法更改对象的类型。你的对象模型似乎错了。 您要么删除未完成的要约并从中创建已接受的要约(看起来就像您当前正在做的那样),但在创建具有新标识的新对象时可能会丢失关系(您也可以在删除旧对象之前复制它们)。或者您希望保留相同的对象并更改其状态。

如果您想保持相同的身份,请预先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

答案 1 :(得分:3)

不要试图将这些自定义类添加到您的实体框架模型中,只需将它们创建为普通的c#类,然后使用投影将实体框架生成的类转换为您自己的类,例如。

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 */};