2015-03-10 3 views
4

SQL Layer:Entity Framework наследование

У меня есть таблица

enter image description here

Entity Framwork слой:

У меня есть следующее правило: все предложения, которые имеют государство null, являются выдающимися предложениями, State is true - Accepted offers, State is false - отклоненные предложения. Кроме того, часть полей используется только для выдающихся, частично - только для Accepted и т. Д. Я использую первый подход к базе данных, поэтому я обновил модель EF из базы данных и переименовал объект Offer в базу предложений и создал 3 дочерних класса:

enter image description here

он отлично работает для добавления/выбора объектов/записей. Прямо сейчас я хочу «переместить» предложение из приглашения принять предложение, поэтому мне нужно установить Status = true (от Status is null) для соответствующей записи. Но как это сделать с помощью Entity Framework? Если я пытаюсь выбрать выдающееся предложение, как принять предложение я получаю ссылку на нулевой (и понятно почему)

// 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 сущности я получаю следующее сообщение об ошибке:

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.

AcceptOffer:

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

DeclineOffer:

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

OutstandingOffer:

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

Как это сделать правильно? Конечно, я могу выбрать запись, удалить из БД и добавить новую с соответствующим значением состояния, но как это сделать обычно?

+0

вы должны прочитать все три статьи [здесь] (http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1- таблица на иерархическом-ТРН). – tschmit007

+0

не нашел ответа на мой вопрос в этих статьях –

+5

С точки зрения ООП. Ты не. Класс - это вещь. Это как сказать, как вы бросаете «Кошку» в «Собака», когда они оба «Животные». Это не имеет никакого смысла. Так что вы делаете неправильно. Класс никогда не должен представлять состояние. – Aron

ответ

6

Вы не можете изменить тип объекта после его создания. Ваша объектная модель кажется неправильной. Либо вы удаляете выдающееся предложение, либо получаете от него принятое предложение (похоже, что вы сейчас делаете), но вы можете потерять отношения, когда вы создали новый объект с новым идентификатором (вы также можете скопировать их перед удалением старого объекта) , Или вы хотите сохранить один и тот же объект и изменить его состояние.

Если вы хотите сохранить идентичность, то preffer 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; } 
} 

Если вы все еще хотите, чтобы изменить тип объекта и сохранить свою идентичность, то вы можете использовать хранимые процедуры; как заявил Ноам Бен-Ами (владелец PM для EF): Changing the type of an entity.

+0

спасибо, но на самом деле, я не знаю, какая архитектура в этом случае правильная. Посмотрите мои добавленные заметки. –

+0

I-образная композиция будет в порядке. Вы можете нанять архитектора программного обеспечения. – Guillaume

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

Это работает, если вы не хотите изменять объекты. – Guillaume