4

SQL Layer:

I have a table

enter image description here

Entity Framwork Layer:

I have the following rule: all Offers, which have State is null, are Outstanding offers, State is true are Accepted offers, State is false are Declined offers. Also, part of fields used only for Outstanding, part - only for Accepted etc... I use Database first approach, so, I updated EF model from DB and renamed Offer entity to OfferBase and created 3 child classes:

enter image description here

it works fine for add/select entities/records. Right now I want to "move" offer from outstanding to accept offer, so, I need to set Status=true (from Status is null) for appropriate record. But how to do it by Entity Framework? If I try to select outstanding offer as Accept offer I get an null reference (and clearly why)

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

if I try to select as OfferBase entity I get the following error:

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;

ADDED NOTES ABOUT ARCHITECTURE:

I have 3 types of Offer entity. There are: AcceptOffer, DeclineOffer and 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...]

How to do it correctly? Of course, I can select a record, remove from DB and add new with appropriate state value, but how to do it normally?

6
  • you should read all three articles here. Commented Mar 10, 2015 at 17:54
  • did not find an answer my question in these articles Commented Mar 10, 2015 at 18:17
  • 5
    From an OOP point of view. You do not. A class is a thing. Its like saying how do you cast a Cat into a Dog, when they are both Animals. It makes no sense. So what you are doing is wrong. A class should never represent state. Commented Mar 13, 2015 at 10:15
  • I think the only way that you can change the discriminators in SQL that are used by Entity Framework in TPH (Table Per Hierarchy) scenarios is through a Stored Procedure. That being said, if it's a Polymorphic object that can change, then TPH isn't really as useful as it seems, because it falsely represents that objects in the table could belong to any class in the Hierarchy. Commented Mar 13, 2015 at 10:18
  • @Aron. I understand, that OOP does not allow cast a Cat into a Dog. I just ask how to solve my situation Commented Mar 18, 2015 at 19:26

2 Answers 2

6
+50

You can't change the type of an object once it's created. Your object model seems wrong. Either you delete the outstanding offer and create an accepted offer from it (looks like what you are currently doing) but you may lose relations as you created a new object with a new identity (you can also copy them before removing the old object). Or you want to keep the same object and change its state.

If you want to keep the same identity then preffer composition over inheritance.

Your code could look like this :

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

If you still want to change the type of the object and keep its identity then you may use stored procedures ; as stated by Noam Ben-Ami (PM owner for EF) : Changing the type of an entity.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you, but really, I don't know which architecture is correct in this case. Look at my added notes.
I -think- composition will be ok. You may hire a software architect.
3

Rather than trying to add these custom classes to your entity framework model, just create them as normal c# classes and then use a projection to convert from the entity framework generated class to your own class e.g.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.