2

エンティティ A と B があり、A と B の間に 2 つの異なる 1 対 1 の関連付けを作成したいと考えています。A はプリンシパルとしての役割を果たす必要があります。このような:

public class A 
{
    public int Id {get; set;}
    public B B1 {get; set;}
    public B B2 {get; set;}
}

public class B
{
    public int Id {get; set;}
}

EF は 1 対 1 の外部キーの関連付けをサポートしていないため、EF で作業モデル/データベースを作成できません。私には、これは深刻な制限のように思えます。今後のバージョンの EF でこのような関連付けをサポートする予定はありますか?

これを機能させるための最善の回避策は何ですか。1 対 2 多の関連付けを 2 つ作成することについては知っています。ただし、それでは B がプリンシパルになり、カスケード削除で問題が発生します。


私の質問に答えてくれてありがとう。以下は、私がやりたいことの例です。つまり、エンティティ A と別のエンティティ B の間に 2 つ (またはそれ以上) の 1 対 1 の関連付けを作成します。これは、EF が vNext でサポートできるものですか?悪い考えですか?

もう一度ありがとう、メリジン

public class A 
{
    public int Id {get; set;}

    public int B1_Id {get; set;}
    public B B1 {get; set;}

    public int B2_Id {get; set;}
    public B B2 {get; set;}
}

public class B
{
    public int Id {get; set;}
}

public class SampleContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>().HasKey(c => c.Id);
        modelBuilder.Entity<B>().HasKey(c => c.Id);

        modelBuilder.Entity<A>().HasRequired(c => c.B1).WihOptional().ForeignKey(x=>x.B1_Id);
        modelBuilder.Entity<A>().HasRequired(c => c.B2).WihOptional().ForeignKey(x=>x.B2_Id);
    }
}
4

3 に答える 3

4

「v-Next」がEntityFramework6の場合、いいえ、EF 6で計画されているすべての機能のロードマップに示されているように、1対1の外部キーの関連付けをサポートしていないようです。

また、一意の制約のサポートがロードマップに含まれておらず、UserVoiceで「レビュー中」とマークされていることもわかります。

1対1の外部キーの関連付けは、基本的に、外部キー列に一意の制約がある1対多の関連付けであるため、一意の制約のサポートが利用可能になるまで、1対1のFKの関連付けは実装されないと思います。 。Aそれがあなたの2つの関係のプリンシパルであることを望むなら、それは特に必要です。現在、EFは、プリンシパルのキーが主キーではなく、一意の制約を持つ列である関係をサポートしていません。

このブログ投稿では、この機能が「延期」されていると説明されているので、EF7に期待しましょう。

于 2013-02-11T20:40:50.007 に答える
1

おそらく用語の問題です。コード ファースト EF では、EF では、プリンシパルと依存関係の両方で相互に外部キーを使用したり、プリンシパルとは無関係の独自の主キーを持つ依存関係との 1 対 1 の関係を持つことはできません。あなたの例では、2 つのナビゲーション プロパティが必要な場合のようです。厳密に言えば、1:1 ではありません。同じテーブルに 2 つの関係があるためです。タイプ1:1の2つの関係があります。EFはこれを多対1と見なします。

真の 1 対 1 の関係がある場合、EF は依存関係にプライマリ キーと同じプライマリ キーを持たせたいと考えます。
原則と従属の両方で複数の NAVIGATION プロパティを定義できます。これにより、インデックスが作成されます。

そのため、多対 1 構成を調査することをお勧めします。プライマリに DB レベルで OPTINAL 外部キーを持たせたい場合は、後で移行中またはスクリプトを使用してこの FK を追加する必要があります。しかし、間違いなく、これはプリンシパルの OPTIONAL FK ではなく、ビジネス ロジック/ルール チェックとして最もよく見られます。そうです、DB で可能なことを正確に一致させるには制限があります。
しかし、コードファーストのシナリオで実際に必要かどうかは疑問です。

ここでの巧妙なトリックは、最初にコードで必要なものをDBで正確にモデル化することです。EF Powertool nuget を使用して、DB から Codefirst を再構築します。

目的のテーブル関係のみを含む EG ミニ DB。ソリューションで新しいプロジェクトを作成します。Entity Framework Powertools をインストールします。次に、新しいプロジェクトで右クリック オプションを使用して、「最初に DB からコードをリバース エンジニアリング」します。

可能であれば、最初にコードでそれを構築する方法を示しています.... :-)

あなたが達成したいと思うこと...コードサンプルを参照してください(あなたが作っている点を誤解していたらごめんなさい)コードはNUGETがロードされた場合に実行されるべきです

 using System.Data.Entity;
    namespace EF_DEMO
    {
    class FK121
    {
        public static void ENTRYfk121(string[] args)
        {
            var ctx = new Context121();
            ctx.Database.Create();
            System.Console.ReadKey();
        }
    }
    public class Main
    {
         public int MainId { get; set; }
         public string BlaMain { set; get; }
         public int? Sub1Id   { set; get; }    // Must be nullable since we want to use EF foreign key
         public int? Sub2Id { set; get; } // Must be nullable since we want to use EF foreign key
        public virtual Sub Sub1 { get; set; }  // Reverse navigation
        public virtual Sub Sub2 { get; set; }  // Reverse navigation
        //  you may also need
        public virtual ICollection<Sub> Subs { get; set; }
    }
    public class Sub
    {
       public int SubId { get; set; }   // Deliberately DIFFERENT KEY TO MAIN.... not 1:1 so this is possible 
       public string blasub { set; get; }
       public int MainId { set; get; } //set in API   , this the FK  
       public virtual Main Main { get; set; } // van to Principal
    }
    public class Context121 : DbContext
    {
        static Context121()
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>());
        }
        public Context121()
            : base("Name=Demo") { } // webconfig required to match 
        public DbSet<Main> Mains { get; set; }
        public DbSet<Sub> Subs { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Main>().HasKey(t => t.MainId)
                        .HasOptional(t => t.Sub1)
                        .WithMany()
                        .HasForeignKey(t=>t.Sub1Id) ; // tell EF the field is in POCO, use this please, otherwise it will create it.

            modelBuilder.Entity<Main>()
                        .HasOptional(t => t.Sub2).WithMany()
                        .HasForeignKey(t=>t.Sub2Id);

            modelBuilder.Entity<Sub>()
                        .HasKey(t => t.SubId)
                        .HasRequired(q => q.Main)
                        .WithMany()
                        .HasForeignKey(t => t.MainId);
        }
    }
}

ウェブコンフィグ....

 <connectionStrings>
   <add name="Demo" connectionString="Data Source=localhost;Initial Catalog=Demo;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework"
        providerName="System.Data.SqlClient" />
  </connectionStrings>
于 2013-02-11T12:29:28.000 に答える
0

どのような問題を解決する必要があるか説明してください。これは、EF 5.0 での 1 対 1 マッピングのサンプルです。

class Program
{
    static void Main(string[] args)
    {
        using (var context = new SampleContext())
        {
            var mainEntity = new MainEntity();
            mainEntity.DetailEntity = new DetailEntity();

            context.SaveChanges();
        }
    }
}

public class SampleContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MainEntity>().HasKey(c => c.Id);
        modelBuilder.Entity<DetailEntity>().HasKey(c => c.Id);

        modelBuilder.Entity<MainEntity>().HasOptional(c => c.DetailEntity).WithRequired(p => p.MainEntity);
        modelBuilder.Entity<DetailEntity>().HasRequired(c => c.MainEntity).WithOptional(p => p.DetailEntity);
    }

    public virtual DbSet<MainEntity> MainEntities { get; set; }

    public virtual DbSet<DetailEntity> DetailEntities { get; set; }
}

public class MainEntity
{
    public int Id { get; set; }

    public DetailEntity DetailEntity { get; set; }
}

public class DetailEntity
{
    public int Id { get; set; }

    public MainEntity MainEntity { get; set; }
}
于 2013-02-11T07:43:54.957 に答える