0

저는 몇 시간 동안 이미 검색 중이므로 문제를 찾을 수 없습니다.Entity Framework가 테이블에 중복 된 중복 식별자를 추가합니다.

Entity Framework의 Fluent API 코드 첫 번째 TPH 앱을 구축하고 있습니다. Add-Migration EF add의 "Type"열은 잘되지만 중복 Discriminator 열 ("Type"으로 덮어 써야 함)을 추가합니다. Map을 사용하여 Type 열 이름과 가능한 값을 지정합니다.이 방법은 대부분의 도메인 모델에서 잘 작동하는 것으로 보이지만이 중 하나는 중복 된 두 번째 discriminator 열을 가져오고 이유를 찾을 수없는 것 같습니다. Bond는 도메인 모델에서 Asset을 상속받습니다.

Heres는 내 코드 :

public class BondConfiguration : EntityTypeConfiguration<Bond> 
{ 
    public BondConfiguration() 
    { 
     Property(b => b.IssueDate) 
      .HasColumnName("BondIssueDate") 
      .HasColumnType(DatabaseVendorTypes.TimestampField) 
      .IsRequired(); 

     Property(b => b.MaturityDate) 
      .HasColumnName("BondMaturityDate") 
      .HasColumnType(DatabaseVendorTypes.TimestampField) 
      .IsRequired(); 

     HasRequired(b => b.Currency).WithRequiredDependent(); 

     Property(b => b.Coupon.Rate); 

     Property(b => b.Coupon.Amount); 

     Property(b => b.FaceValue) 
      .HasColumnName("BondFaceValue") 
      .IsRequired(); 
    } 
} 

public class AssetConfiguration : EntityTypeConfiguration<Asset> 
{ 
    public AssetConfiguration() 
    { 
     Property(a => a.IsDeleted).HasColumnName("IsDeleted"); 

     HasKey(a => a.Id); 

     ToTable("tbl_Asset"); 

     Property(a => a.Id) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) 
      .HasColumnName("AssetId"); 

     Property(a => a.Name) 
      .HasColumnName("AssetName") 
      .IsRequired(); 

     Property(a => a.Isin) 
      .HasColumnName("AssetISIN"); 

     Map<Bond>(p => p.Requires("AssetClass").HasValue((int)AssetClass.Bond)); 
    } 
} 

도메인 모델 :

public class Bond : Asset 
{ 
    public DateTime IssueDate { get; set; } 

    public DateTime MaturityDate { get; set; } 

    public BondCoupon Coupon { get; set; } 

    public Currency Currency { get; set; } 

    public decimal FaceValue { get; set; } 

    public IEnumerable<ValidationRule> SetCoupon(decimal amount, decimal rate) 
    { 
     var newCoupon = new BondCoupon 
     { 
      Rate = rate, 
      Amount = amount 
     }; 

     if (Validate(new SetBondCouponValidator(newCoupon),out IEnumerable<ValidationRule> brokenRules)) 
     { 
      Coupon = new BondCoupon 
      { 
       Rate = rate, 
       Amount = amount 
      }; 
     } 
     return brokenRules; 
    } 
} 

public abstract class BaseAsset<T> : BaseEntity<T> where T : BaseEntity<T>, new() 
{ 
    public string Name { get; set; } 

    public string Isin { get; set; } 
} 

public class Asset : BaseAsset<Asset>, IEntityRoot 
{ 
} 

public class BaseEntity<T> where T : BaseEntity<T>, new() 
{ 
    public int Id { get; set; } 

    public bool IsDeleted { get; set; } 

    public bool Validate(IValidator validator, out IEnumerable<ValidationRule> brokenRules) 
    { 
     brokenRules = validator.GetBrokenRules(); 
     return validator.IsValid(); 
    } 
} 
+0

문제를 재현 할 수 있도록'Asset'과'Bond' 클래스를 추가 할 수 있습니까? –

+0

방금 ​​도메인 모델을 추가했습니다. 이것 좀 봐 줘서 고마워. –

+0

제공된 모델로 재생산 할 수 없습니다. 'Asset' 또는'Bond'를 상속받은 동일한 프로젝트 (어셈블리)에 다른 클래스가 있습니까? –

답변

3

EF6 상속 중 하나를 사용할 때 매우주의해야합니다. EF는 동일한 어셈블리에서 리플렉션을 사용하여 EF 상속의 일부인 엔티티 중 일부 또는 전체를 직접 또는 간접적으로 상속하며 엔티티 계층 구조의 일부로 간주합니다. EF 모델.

그래서 단지

public Asset2 : Asset { } 

는이 Bond 클래스의 판별 자 컬럼 설정을 사용하도록 구성되어 있지 있기 때문에 표준 Discriminator 열을 소개 충분하다 (이 Equity를 불렀다 실제 경우) 다른 클래스를 추가.

이 동작은 사용자와 같은 예상치 못한 오류의 원인이며 명시 적으로 구성된 파생 클래스 만 고려되는 EF 코어에서 변경되었습니다.

EF6에서는 이러한 클래스를 NotMapped 속성으로 표시하거나 Ignore 유창한 API를 사용하거나 엔티티로 올바르게 매핑 할 수 있습니다.

+1

그래, 이것이 코어에서 수정 된 EF6의 버그입니까? 고맙습니다. 모델을 조정하고 주식 구성을 포함 시켰습니다. 이후에 이전을 재개했습니다. 판별 자 열은 마이그레이션 중에 제거됩니다. 문제 해결됨. –

1

여기에 완전한 비 생식입니다. EntityTypeConfigurations가 OnModelCreating에 유선되어 있고 모델이 초기화 될 때 실제로 실행 중인지 확인하십시오. 또한 "tbl_"접두사가있는 테이블의 이름을 지정하지 마십시오. (일부)

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Data.Entity.ModelConfiguration; 
using System.Data.SqlClient; 
using System.Linq; 

namespace ConsoleApp8 
{ 

    public class Bond : Asset 
    { 
     public DateTime IssueDate { get; set; } 

     public DateTime MaturityDate { get; set; } 

     //public BondCoupon Coupon { get; set; } 

     //public Currency Currency { get; set; } 

     public decimal FaceValue { get; set; } 


    } 

    public abstract class BaseAsset<T> : BaseEntity<T> where T : new() 
    { 
     public string Name { get; set; } 

     public string Isin { get; set; } 
    } 

    public class Asset : BaseAsset<Asset> 
    { 
    } 

    public class BaseEntity<T> where T : new() 
    { 
     public int Id { get; set; } 

     public bool IsDeleted { get; set; } 


    } 
    public class BondConfiguration : EntityTypeConfiguration<Bond> 
    { 
     public BondConfiguration() 
     { 

      Property(b => b.FaceValue) 
       .HasColumnName("BondFaceValue") 
       .IsRequired(); 
     } 
    } 
    public enum AssetClass 
    { 
     Bond = 1 
    } 
    public class AssetConfiguration : EntityTypeConfiguration<Asset> 
    { 
     public AssetConfiguration() 
     { 
      Property(a => a.IsDeleted).HasColumnName("IsDeleted"); 

      HasKey(a => a.Id); 

      ToTable("Asset"); 

      Property(a => a.Id) 
       .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity) 
       .HasColumnName("AssetId"); 

      Property(a => a.Name) 
       .HasColumnName("AssetName") 
       .IsRequired(); 

      Property(a => a.Isin) 
       .HasColumnName("AssetISIN"); 

      Map<Bond>(p => p.Requires("AssetClass").HasValue((int)AssetClass.Bond)); 
     } 
    } 

    class Db : DbContext 
    { 
     public DbSet<Bond> Bonds { get; set; } 
     public DbSet<Asset> Assets { get; set; } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      modelBuilder.Configurations.Add(new AssetConfiguration()); 
      modelBuilder.Configurations.Add(new BondConfiguration()); 
     } 
    } 



    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(); 


     } 
    } 
} 

출력 :

CREATE TABLE [dbo].[Asset] (
    [AssetId] [int] NOT NULL IDENTITY, 
    [AssetName] [nvarchar](max) NOT NULL, 
    [AssetISIN] [nvarchar](max), 
    [IsDeleted] [bit] NOT NULL, 
    [IssueDate] [datetime], 
    [MaturityDate] [datetime], 
    [BondFaceValue] [decimal](18, 2), 
    [AssetClass] [int], 
    CONSTRAINT [PK_dbo.Asset] PRIMARY KEY ([AssetId]) 
)