Question

i use Entities Framework Code First and I've next POCO classes:

 public class Product 
    {       
        public int ProductID { get; set; }
        public int Title{ get; set; }
        public int Price { get; set; }

        public int ProductCategoryID { get; set; }
        public virtual ProductCategory ProductCategory { get; set; }
    }

  public class ProductCategory 
    {
        public int ProductCategoryID { get; set; }        
        public int Title{ get; set; }
        public virtual ICollection<Product> Products { get; set; }
    }

So let the product has a simple method MakeSale which depends on ProductCategory

public int void GiveSale()
{
  //I can do like this ...
    switch (this.ProductCategoryID)
    {
        case 1: return this.Price * 0,8;
        break;
        case 2: return 0;
        ...         
    }
 }

But I do not like this approach, i want use OOP and have something like this:

public class Dress : Product 
{
  public override int void GiveSale()
   {
      return this.Price * 0,8;
   }
}

public class Shoes : Product 
{
  public override int void GiveSale()
   {
      return 0;
   }
}

How can I do this with Entities Framework and saving ease of use with my entities?

Was it helpful?

Solution

You can try to use EF Inheritance for your objects. It's also available in Code First - http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx

There are 3 different approaches based on what you need:

  1. Table per Hierarchy - when all objects are related to the same table
  2. Table per Type - when all classes can have common data in shared table, and all specific fields is mapped to another table
  3. Table per concrete class - when all classes have own table. In that case common data structure will be duplicated in each table

You need to map your Dress, Shoes entities based on some data in OnModelCreating method. For example:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Entity<Product>()
            .Map<Dress>(m => m.Requires("ProductCategoryID").HasValue(1))
            .Map<Shoes>(m => m.Requires("ProductCategoryID").HasValue(2));
}

In that case when you will load them from DBContext, it will create needed type automatically:

List<Product> products = dbContext.Products.ToList();
foreach(var product in products)
{
    var sale = product.GiveSale();
    if (product is Dress) Console.WriteLine("It's dress!");
    if (product is Shoes) Console.WriteLine("It's a pair of shoes!");       
}

and then you can update data, and save Dress\Shoes as usual Poco objects in Code first by calling SaveChanges

OTHER TIPS

EF maps objects into tables and it's quite obvious approach, but when getting into polymorphism, well, DB is not our best friend.

Notice how EF makes your entities partial classes. This is for you to extend them. So, you can write your extended class and put your virtual method there, and go on and implement other derived classes.

So let's say this is the generated EF class:

public partial class Entity
{
    public int ID { get; set; }
    public string Name { get; set; }
    ...
}

Then, on another file, write the extended class under the same namespace as Entity:

public partial class Entity
{
      public virtual int GiveSale()
      {
           return 0;
      }
}

Continue with the rest of your hierarchy:

public class Derived : Entity
{
     public override int GiveSale()
     {
           return your calculation;
     }
}

This way you still have the entity framework class and you're free to extend it and even make it the base class of your hierarchy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top