1

抽象クラスを使用しているときに外部キーを正しいテーブルにマッピングする際に問題がありました。抽象クラスと流暢なAPIを使用しているときに、外れた外部キーがあります

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」外部キーを置くデータベースの作成Iそれが必要ですが) "FK_Order"外部キーは、 "OrderEntries"テーブルの代わりに "Entities"テーブルに配置されます。クラス "OrderEntry"の抽象プロパティを具体的に変更すると、すべてがOKです。この場合は抽象クラスintを避けなければならないのですか?

答えて

0

モデルを試しましたが、問題を再現できません。私はFK_Orderの列をOrderEntriesテーブルに取得し、期待通りにEntitiesテーブルには取得しません。

コンソールアプリのProgram.csにもコピーできます(参考までにEntityFramework.dllSystem.ComponentModel.DataAnnotations.dllも追加できます)。

UserDeviceModelOrderの3つのダミークラスを作成して、コードをコンパイルして実行しました。しかし、他のクラスはあなたの質問のコピーです。

質問は次のとおりです。間違ったマッピングが発生する可能性のあるコードと、コードとの重要な違いはどこですか?

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(); 
      } 
     } 
    } 
} 
+0

ご返信ありがとうございます。コンテキストと私の大きな違いは、定義したdbsetにあります。エンティティdbsetだけを定義し、他のものは定義しませんでした。私は仕事に戻るとすぐにdbsetを追加しようとします。 – Glopper

+0

OK、それぞれの抽象クラスのためのdbsetの作成が解決策であるようです。そうでなければ、 "ToTable"を使ったマッピングは、対応するdbsetを持つ最初の抽象クラスが見つかるまで、継承階層を通過すると仮定します。私は答えとしてあなたの記事をタグ付けしました、もう一度ありがとうございます。 – Glopper

関連する問題