0

私は数時間前から検索していましたが、問題を見つけることができませんでした。Entity Frameworkはテーブルに冗長な重複ディスクリプタ列を追加します

私はEntity Framework Fluent ApiコードファーストTPHアプリケーションを構築しています。私はAdd-Migration EF addの「Type」列は問題ありませんが、Discriminatorの冗長列も追加します(「Type」で上書きする必要があります)。私はマップを使用してタイプの列名と可能な値を指定していますが、このアプローチはほとんどのドメインモデルでうまくいくようですが、これは冗長な第2の識別器列を取得します。 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モデル。

Bondクラスの識別子列の設定を使用するように構成されていないので、だから(それはEquityと呼ばれていますあなたの本当の場合)

public Asset2 : Asset { } 

を別のクラスを追加すると、標準Discriminator列を導入するのに十分です。

この動作は、あなたのような予期しないエラーの原因であり、明示的に構成された派生クラスのみが考慮されるEFコアで変更されています。

EF6では、そのようなクラスをNotMapped属性にマークするか、Ignore流暢なAPIを使用するか、エンティティとして適切にマッピングします。

+1

これはコアで修正されたEF6のバグですか?ありがとう、私はモデルと株式構成を調整し、その後、私は移行を再生成しました。ディスクリミネータ列は、移行時に削除されます。問題が解決しました。 –

1

はここで完全な非REPROです。 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]) 
) 
関連する問題