неуместные внешние ключи при использовании абстрактных классов и свободного API - PullRequest
1 голос
/ 20 октября 2011

У меня проблема с отображением внешних ключей в правильную таблицу при использовании абстрактных классов.Вот моя модель:

public abstract class Entity
{
    public Guid UID { get; set; }
}

public abstract class Product : Entity
{
    public DeviceModel Model { get; set; }
    public User Operator { get; set; }
}

public abstract class OrderEntry : Entity
{
    public Order Order { get; set; }
}

public class Device : Product
{
    public String Reference { get; set; }
    public String Serial { get; set; }
    public String SoftwareVersion { get; set; }
}

public class OrderEntryDevice : OrderEntry
{
    public DeviceModel Model { get; set; }
}

И текущие конфигурации API (схема TPT):

public class EntityConfiguration : EntityTypeConfiguration<Entity>
{
    public EntityConfiguration()
    {
        ToTable("Entities");

        HasKey(t => t.UID);
    }
}

public class ProductConfiguration : EntityTypeConfiguration<Product>
{
    public ProductConfiguration()
    {
        ToTable("Products");

        HasOptional(t => t.Operator)
            .WithMany()
            .Map(t => t.MapKey("FK_Operator"))
            .WillCascadeOnDelete(false);
    }
}

public class OrderEntryConfiguration : EntityTypeConfiguration<OrderEntry>
{
    public OrderEntryConfiguration()
    {
        ToTable("OrderEntries");

        HasRequired(t => t.Order)
            .WithMany()
            .Map(t => t.MapKey("FK_Order"))
            .WillCascadeOnDelete(false);
    }
}

public class DeviceConfiguration : EntityTypeConfiguration<Device>
{
    public DeviceConfiguration()
    {
        ToTable("Devices");

        Property(t => t.Reference)
            .IsRequired();

        Property(t => t.Serial)
            .IsRequired();

        HasRequired(t => t.Model)
            .WithMany()
            .Map(t => t.MapKey("FK_Model"))
            .WillCascadeOnDelete(false);
    }
}

public class OrderEntryDeviceConfiguration : EntityTypeConfiguration<OrderEntryDevice>
{
    public OrderEntryDeviceConfiguration()
    {
        ToTable("OrderEntriesDevice");

        HasRequired(t => t.Model)
            .WithMany()
            .Map(t => t.MapKey("FK_Model"))
            .WillCascadeOnDelete(false);
    }
}

При создании базы данных внешний ключ "FK_Operator" помещается в таблицу "Products"(именно там, где я хочу), но внешний ключ "FK_Order" помещается в таблицу "Entities" вместо таблицы "OrderEntries".Если я изменю абстрактное свойство класса "OrderEntry" на конкретное, то все в порядке.Нужно ли избегать абстрактного класса в этом случае?

1 Ответ

0 голосов
/ 20 октября 2011

Я пробовал вашу модель и не могу воспроизвести проблему.Я получаю столбец FK_Order в таблице OrderEntries, а не в таблице Entities - как и ожидалось.

Вы можете скопировать следующее в Program.cs консольного приложения (также добавьте EntityFramework.dll иSystem.ComponentModel.DataAnnotations.dll к ссылкам).

Я создал три фиктивных класса для User, DeviceModel и Order, чтобы код был скомпилирован и запущен.Но другие классы являются копией вашего вопроса.

Вопрос в том, где важное различие между кодом ниже и вашим кодом, которое может привести к неправильному отображению у вас?

using System;
using System.Linq;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace EFAbstractTest
{
    public class User
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public class DeviceModel
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public class Order
    {
        [Key]
        public Guid UID { get; set; }
        public string Name { get; set; }
    }

    public abstract class Entity
    {
        public Guid UID { get; set; }
    }

    public abstract class Product : Entity
    {
        public DeviceModel Model { get; set; }
        public User Operator { get; set; }
    }

    public abstract class OrderEntry : Entity
    {
        public Order Order { get; set; }
    }

    public class Device : Product
    {
        public String Reference { get; set; }
        public String Serial { get; set; }
        public String SoftwareVersion { get; set; }
    }

    public class OrderEntryDevice : OrderEntry
    {
        public DeviceModel Model { get; set; }
    }

    public class EntityConfiguration : EntityTypeConfiguration<Entity>
    {
        public EntityConfiguration()
        {
            ToTable("Entities");

            HasKey(t => t.UID);
        }
    }

    public class ProductConfiguration : EntityTypeConfiguration<Product>
    {
        public ProductConfiguration()
        {
            ToTable("Products");

            HasOptional(t => t.Operator)
                .WithMany()
                .Map(t => t.MapKey("FK_Operator"))
                .WillCascadeOnDelete(false);
        }
    }

    public class OrderEntryConfiguration : EntityTypeConfiguration<OrderEntry>
    {
        public OrderEntryConfiguration()
        {
            ToTable("OrderEntries");

            HasRequired(t => t.Order)
                .WithMany()
                .Map(t => t.MapKey("FK_Order"))
                .WillCascadeOnDelete(false);
        }
    }

    public class DeviceConfiguration : EntityTypeConfiguration<Device>
    {
        public DeviceConfiguration()
        {
            ToTable("Devices");

            Property(t => t.Reference)
                .IsRequired();

            Property(t => t.Serial)
                .IsRequired();

            HasRequired(t => t.Model)
                .WithMany()
                .Map(t => t.MapKey("FK_Model"))
                .WillCascadeOnDelete(false);
        }
    }

    public class OrderEntryDeviceConfiguration : EntityTypeConfiguration<OrderEntryDevice>
    {
        public OrderEntryDeviceConfiguration()
        {
            ToTable("OrderEntriesDevice");

            HasRequired(t => t.Model)
                .WithMany()
                .Map(t => t.MapKey("FK_Model"))
                .WillCascadeOnDelete(false);
        }
    }

    public class MyContext : DbContext
    {
        public DbSet<Entity> Entities { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<DeviceModel> DeviceModels { get; set; }
        public DbSet<Order> Orders { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new EntityConfiguration());
            modelBuilder.Configurations.Add(new ProductConfiguration());
            modelBuilder.Configurations.Add(new OrderEntryConfiguration());
            modelBuilder.Configurations.Add(new DeviceConfiguration());
            modelBuilder.Configurations.Add(new OrderEntryDeviceConfiguration());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var ctx = new MyContext())
            {
                // some query, just to trigger database creation
                ctx.Orders.Count();
            }
        }
    }
}
...