1

私は最初にコードで少し EF を試みています - そして、私自身の単純な例でどこが間違っているのかわかりません。アイデアが足りないので、どこが間違っているのかを突き止めたいと思います...

まず、場所を表す単純な POCO クラス - 場所は、RadioStation または Merchant にすることができます。追加のフィールドは追加していません (後で追加します)。そのため、現時点では、できる限り単純な構成の TPH にすぎません。

namespace EFDataClasses.Entities
{

  public class RadioStation : Location
  {
    public RadioStation()
    {
    }

  }

  public class Merchant : Location
  {
    public Merchant()
     {
     } 
   }


  public class Location
  {
   public Location()
   {

   }

public int Loc_ID { get; set; }
public string Loc_Code { get; set; }
public string Loc_Name { get; set; }
public string  Loc_Type {get;set;}

 }
}

次に設定クラス:

namespace EFDataClasses.Mapping
{


  public class LocationMap : EntityTypeConfiguration<Location>
  {
    public LocationMap()
    {
      // Primary Key
      this.HasKey(t => t.Loc_ID);

      // Properties
      this.Property(t => t.Loc_ID)
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

      // Properties
      this.Property(t => t.Loc_Code)
          .IsRequired()
          .HasMaxLength(50);

      this.Property(t => t.Loc_Name)
          .IsRequired()
          .HasMaxLength(50);


      this.Property(t => t.Loc_ID).HasColumnName("Loc_ID");
      this.Property(t => t.Loc_Code).HasColumnName("Loc_Code");
      this.Property(t => t.Loc_Name).HasColumnName("Loc_Name");

      //my discriminator property
      this.Property(t => t.Loc_Type).HasColumnName("Loc_Type").HasColumnType("varchar").HasMaxLength(50).IsRequired();

      // Table & Column Mappings
      this.Map(m =>
      {
        m.ToTable("Location");
        m.Requires("Loc_Type").HasValue("Location");
      }
        )
        .Map<RadioStation>(m =>
        {
          m.ToTable("Location");
          m.Requires("Loc_Type").HasValue("RadioStation");
        }
        )
        .Map<Merchant>(m =>
        {
          m.ToTable("Location");
          m.Requires("Loc_Type").HasValue("Merchant");
        }
        )
        ;



    }
  }
}

コンテキストは次のとおりです。

namespace EFDataClasses
{
  public class MyContext : DbContext
  {
    static MyContext()
    {
      Database.SetInitializer<MyContext>(new DropCreateDatabaseAlways<MyContext>());
    }

    public DbSet<EFDataClasses.Entities.Location> Locations {get; set;}

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

最後に、ラジオ局を追加しようとするプログラム クラスです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EFConsole
{
  class Program
  {
    static void Main(string[] args)
    {

      var db = new EFDataClasses.MyContext();
      db.Locations.Add(new EFDataClasses.Entities.RadioStation() { Loc_Name = "Radio Station Name 1",  Loc_Code = "RD1" });
      int chngs = db.SaveChanges();
      System.Diagnostics.Debugger.Break();

    }
  }
}

私が得ているエラーは、Loc_Type が必須フィールドであることを示す検証エラーです。ここでの私の印象は、適切な型を選択すると EF がそれを埋めてくれるということです。

適切な場所の種類を追加すると、EF で別のエラーが表示されます....

ああああ!

最後に Location を抽象化したいのですが、それは hasvalue("Location") を削除できるということですか?

ここで先に進みたいのですが、どこが間違っていたのか気になります。ありがとう!

4

2 に答える 2

1

物事を少し複雑にしすぎていると思いますが、それは CF の周りでは危険です。
コードファーストでは、機能する「試行錯誤済み」のパターンに固執する必要があります。そうしないと、物事と構造を混在させると、すぐに問題が発生します。

まず、なぜ Loc_Type をマップして持つ必要があるのでしょうか。つまり、クラス モデルでしょうか。それは不必要です。実際には「クラス」タイプでそれが得られます。クラスタイプは識別子であり、その逆も同様です。

そして、それがエラーが言っていることであり、私が思うに、供給または「マッピングから列を削除する」か何かです。

からドロップするだけで、'Location'問題なく動作します。また、Db を意味のあるものにし、他の側で使用する場合を除き、ほとんどの場合、ディスクリミネーターを指定する必要はありません。ただし、これは問題ありません。

必要に応じて、それを抽象化することができます Location - そして、それは通常行われます.マッピングから削除できると思います.「実際に実装された」クラスのみが「インスタンス化」できるため、マッピングする必要があります.

そして最後に、TPH はさまざまな理由で最も「幸運な」解決策ではなく、最もエラーが発生しやすいと私が考えるすべての中で、TPT、TPC はすべてはるかに「流動的」に機能します。「子クラス」のプロパティをnull以外にすることはできません。などなど、投稿があります。

お役に立てれば。

編集:「隠された」ディスクリミネーターを制御したい場合は、その列のサイズなどを設定するために、その列I thinkを手動で調整してみてくださいmigration file。それが重要な場合(コードは最初に正しい値を選択する必要があります)。物事がどのように機能するかという感覚に重要なことを何も変更しなければ、それは機能するはずです。

于 2012-04-07T22:12:37.517 に答える
1

問題は、列を TPH マッピングの識別子として使用する場合、その列をクラスのプロパティにマップすることもできないことです。これは、EF が .NET クラスの型に基づいてその列の値を制御しているためです。したがって、Loc_Type プロパティを Location 列にマッピングする次の行を削除する必要があります。

// Remove this line:
this.Property(t => t.Loc_Type).HasColumnName("Loc_Type").HasColumnType("varchar").HasMaxLength(50).IsRequired();

識別子列の明示的な列タイプ、サイズなどを指定する必要がある (または望む) 場合は、Map 呼び出しでそれを行うことができます。例えば:

Map(m =>
{
    m.ToTable("Location");
    m.Requires("Loc_Type")
        .HasValue("Location")
        .HasColumnType("varchar")
        .HasMaxLength(50)
        .IsRequired();
}

場所の種類を表すクラスにプロパティを含める必要はありません。Loc_Type に相当する文字列値を取得したい場合は、Location で次のようなものを使用できます。

public virtual string Loc_Type
{
    get { return "Location"; }
}

次に、他のクラスでそれをオーバーライドします。例えば:

public override string Loc_Type
{
    get { return "RadioStation"; }
}

コードの残りの部分は正常に見えます。

于 2012-04-07T23:20:59.817 に答える