在Discriminator列上向Entity Framework生成的表添加链接表

时间:2017-09-19 15:44:36

标签: c# entity-framework

我有以下代码结构:

class Car
class Honda : Car
class Toyota : Car

当然,这会在Discriminator表格中生成Cars列。所以,我们有以下记录:

汽车表:

Id   Discriminator   Color
---------------------------
 1   Honda           Yellow
 2   Honda           Red
 3   Toyota          Yellow

现在,我要做的是通过为每个品牌/型号添加Car来扩展Price信息。但它应该是一个映射表,因为它是按汽车制造的,而不是按汽车“实例”(记录)。

类似的东西:

CarPrices 表格:

CarType     Amount
------------------
Toyota      10000
Honda       11000

基本上我想要一个car.Price.Amount属性,对于Honda,它会获得11,000值。

我想我可以做以下'映射':

public class CarPrice
{
    public CarPrice(Car car, int amount)
    {
        var carType = car.GetType();

        if (carType.BaseType != null && carType.Namespace == "System.Data.Entity.DynamicProxies")
        {
            // Get rid of the EF dynamic proxy wrapper
            carType = carType.BaseType;
        }

        this.CarType = carType.Name;
        this.Amount = amount;
    }

    protected CarPrice()
    {
        // Required by EF
    }

    [Required]
    public int Amount { get; private set; }

    [Key]
    public string CarType { get; private set; }
}

但我不知道如何在Price上执行Car属性,该属性基于其Discriminator映射到CarPrice

class Car
{
  // ...

  // TODO: I only need 'get'
  public virtual CarPrice Price { get; }
}

我必须避免在Cars表中添加新列,因此链接绝对必须发生在现有记录的Discriminator列上。

我该如何处理?也许我可以使用Fluent API将car.Price属性映射到自定义SQL查询或以某种方式将其指向CarPrices表?

我认为解决方案将围绕Mapping Properties of an Entity Type to Multiple Tables in the Database (Entity Splitting)

1 个答案:

答案 0 :(得分:0)

这里没什么特别的。只需将鉴别器添加为实体属性,就可以将其用作外键属性。

EG

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Ef6Test
{

    public class Car
    {
        public int Id { get; set; }
        public string CarTypeName { get; set; }

        [ForeignKey("CarTypeName")]
        public CarType CarType { get; set; }

    }
    public class Honda: Car
    {

    }
    public class Toyota : Car
    {

    }
    public class CarType
    {
        [Key]
        public string Name { get; set; }

        public int Price { get; set; }

    }
    class Db : DbContext
    {
        public DbSet<Car> Cars { get; set; }
        public DbSet<CarType> Prices { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Car>().Map<Honda>(c => c.Requires("CarTypeName").HasValue("Honda"));
            modelBuilder.Entity<Car>().Map<Toyota>(c => c.Requires("CarTypeName").HasValue("Toyota"));
            base.OnModelCreating(modelBuilder);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

            Database.SetInitializer(new DropCreateDatabaseAlways<Db>());

            using (var db = new Db())
            {
                db.Database.Log = m => Console.WriteLine(m);
                db.Database.Initialize(true);
            }

            Console.WriteLine("Hit any key to exit");
            Console.ReadKey();
        }
    }
}