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"클래스의 추상 속성을 구체적으로 변경하면 모든 것이 정상입니다. 나는이 경우 추상 클래스 int를 피할 필요가 있는가?

답변

0

모델을 시도했지만 문제를 재현 할 수 없습니다. OrderEntries 테이블에 FK_Order 열이 있고 테이블에는 예상대로 Entities이 없습니다.

다음을 콘솔 앱의 Program.cs에 복사 할 수 있습니다 (참조에 EntityFramework.dllSystem.ComponentModel.DataAnnotations.dll도 추가 할 수 있음).

컴파일 된 코드를 실행하기 위해 User, DeviceModelOrder에 대한 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

관련 문제