37

私は2つのPOCOクラスを持っています:

注文クラス:

public class Order
{
    public int Id { get; set; }
    public int? QuotationId { get; set; }
    public virtual Quotation Quotation { get; set; }
    ....
}

見積もりクラス:

public class Quotation
{
    public int Id { get; set; } 
    public virtual Order Order { get; set; }
    ....   
}
  • それぞれOrder 、1 つまたはゼロの引用から作成できます。
  • 各見積もり注文を引き起こす可能性があります。

だから私は「1か0」から「1か0」への関係を持っています.APIEFによって最初にコードでこれをどのように実装できますか?Fluent

4

7 に答える 7

38

pocos を次のように変更します。

public class Order
{
    public int OrderId { get; set; }
    public virtual Quotation Quotation { get; set; }
}
public class Quotation
{
    public int QuotationId { get; set; }
    public virtual Order Order { get; set; }
}

これらのマッピング ファイルを使用します。

public class OrderMap : EntityTypeConfiguration<Order>
{
    public OrderMap()
    {
        this.HasOptional(x => x.Quotation)
            .WithOptionalPrincipal()
            .Map(x => x.MapKey("OrderId"));
    }
}

public class QuotationMap : EntityTypeConfiguration<Quotation>
{
    public QuotationMap()
    {
        this.HasOptional(x => x.Order)
            .WithOptionalPrincipal()
            .Map(x => x.MapKey("QuotationId"));
    }
}

この DB があります (0..1-0..1 を意味します):

ここに画像の説明を入力

( Vahid Nasiri氏)に特別な感謝を込めて

于 2013-02-11T19:18:29.560 に答える
28

@Masoudの手順は次のとおりです。

modelBuilder.Entity<Order>()
            .HasOptional(o => o.Quotation)
            .WithOptionalPrincipal()
            .Map(o => o.MapKey("OrderId"));

modelBuilder.Entity<Quotation>()
            .HasOptional(o => o.Order)
            .WithOptionalPrincipal()
            .Map(o => o.MapKey("QuotationId"));

それは与えます:

ここに画像の説明を入力

コードを次のように変更します。

modelBuilder.Entity<Order>()
            .HasOptional(o => o.Quotation)
            .WithOptionalPrincipal(o=> o.Order);

それは与えます:

ここに画像の説明を入力

于 2014-11-07T06:38:27.800 に答える
8

http://msdn.microsoft.com/en-us/data/jj591620 EF 関係を参照してください。

優れた本 http://my.safaribooksonline.com/book/-/9781449317867

2010 年 12 月の開発者からの投稿を次に示し ますここで可能な組み合わせ。

依存テーブルがプライマリ テーブルのキーを持つソリューションが可能です。

PK/FK シナリオで両方がプリンシパルである独立したキーが必要な場合は、Fluent API を使用して最初にコードで実行できるとは思いません。彼らがキーを共有している場合は、問題ありません。1:1 オプションは、従属がプライマリからのキーを使用することを前提としています。

ただし、テーブルの 1 つを他のテーブルの前に保存する必要があるためです。外部キーの 1 つをコードで確認できます。または、コードが最初に作成した後に、データベースに 2 番目の外部を追加します。

あなたは近づくでしょう。ただし、両方を外部キーにしたい場合、EFは競合する外部キーについて文句を言います。基本的に、A は B に依存します A EF は、列が null 可能であり、DB で技術的に可能であっても、好きではありません。

ここでは、このテスト プログラムを使用して試してみます。いくつかのオプションを試すには、Fluent API の内容をコメント インしてアウトするだけです。 EF5.0 を INDEPENDENT PK/FK 0:1 から 0:1 で動作させることができませんでした

using System.Data.Entity;
using System.Linq;
namespace EF_DEMO
{
class Program
{
    static void Main(string[] args) {
        var ctx = new DemoContext();
        var ord =  ctx.Orders.FirstOrDefault();
        //. DB should be there now...
    }
}
public class Order
{
public int Id {get;set;}
public string Code {get;set;}
public int? QuotationId { get; set; }   //optional  since it is nullable
public virtual Quotation Quotation { get; set; }
  //....
}
public class Quotation
{
 public int Id {get;set;}
 public string Code{get;set;}
// public int? OrderId { get; set; }   //optional  since it is nullable
 public virtual Order Order { get; set; }
 //...
}
public class DemoContext : DbContext
{
    static DemoContext()
    {
    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DemoContext>());
    }
    public DemoContext()
        : base("Name=Demo") { }
    public DbSet<Order> Orders { get; set; }
    public DbSet<Quotation> Quotations { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
       modelBuilder.Entity<Order>().HasKey(t => t.Id)
                    .HasOptional(t => t.Quotation)
                    .WithOptionalPrincipal(d => d.Order)
                    .Map(t => t.MapKey("OrderId"));  // declaring here  via MAP means NOT declared in POCO
        modelBuilder.Entity<Quotation>().HasKey(t => t.Id)
                    .HasOptional(q => q.Order)
            // .WithOptionalPrincipal(p => p.Quotation)  //as both Principals
            //        .WithOptionalDependent(p => p.Quotation) // as the dependent
            //         .Map(t => t.MapKey("QuotationId"));    done in POCO.
            ;
    }   
}
}
于 2013-02-05T13:43:11.260 に答える
5

この回答から適応させて、これを試してください。

まず、クラスを修正します。

public class Order
{
  public int Id {get; set;}
  public virtual Quotation Quotation { get; set; }
  // other properties
}

public class Quotation
{
  public int Id {get; set;}
  public virtual Order Order { get; set; }
  // other properties
}

次に、流暢な API を次のように使用します。

modelBuilder.Entity<Quotation>()
.HasOptional(quote => quote.Order)
.WithRequired(order=> order.Quotation);

基本的に、1:1 または [0/1]:[0/1] の関係の場合、EF は主キーを共有する必要があります。

于 2013-02-05T13:34:02.420 に答える
1
public class OfficeAssignment
{
    [Key]
    [ForeignKey("Instructor")]
    public int InstructorID { get; set; }
    [StringLength(50)]
    [Display(Name = "Office Location")]
    public string Location { get; set; }

    public virtual Instructor Instructor { get; set; }
}

キー属性

Instructor エンティティと OfficeAssignment エンティティの間には、1 対 0 または 1 の関係があります。オフィスの割り当ては、割り当てられたインストラクターに関連してのみ存在するため、その主キーは Instructor エンティティへの外部キーでもあります。しかし、Entity Framework は InstructorID をこのエンティティの主キーとして自動的に認識することができません。これは、その名前が ID または classnameID の命名規則に従っていないためです。したがって、Key 属性を使用して、それをキーとして識別します。

https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net- mvc-アプリケーション

于 2016-04-28T02:59:57.603 に答える
0

(これは EF 6.4.4 を使用していることに注意してください。)

外部キー プロパティが必要ない限り、指定するのはかなり簡単です。

modelBuilder
.Entity<Order>()
.HasOptional(o => o.Quotation)
.WithOptionalPrincipal(q => q.Order);

modelBuilder
.Entity<Quotation>()
.HasOptional(q => q.Order)
.WithOptionalDependent(o => o.Quotation);

WithOptionalPrincipalここで、との両方の使用法に注意してくださいWithOptionalDependent。これにより、依存側 (例では Quotation) に単一の外部キー列が提供されますが、外部キー プロパティはありません。反対側に外部キーが必要な場合は、「依存」と「プリンシパル」を切り替えます。

(上記の両方の定義を持つ必要はないことに注意してください。WithOptionalDependent反対側がプリンシパルであり、その逆であることを意味するため、必要に応じて一方のみを使用できますが、両側からの関係を指定するとエラーを防ぐことができます物事を二重に宣言することにより、競合が発生するとモデルエラーが発生し、何かを見逃していることがわかります。)

外部キー列にインデックスがありますが、インデックスには一意の制約がありません。独自の一意の制約 (Key IS NOT NULLフィルターが必要) を追加することは可能ですが、機能しないようで、関係を更新するときに例外が発生する場合があります。これは、EF が個別のクエリで更新を実行する「スワッピングの問題」に関連していると思われるため、一意性を強制すると、EF は 2 つのステップでキーを「移動」できなくなります。

EF は、一意の DB 制約なしで、関連付け自体を内部的に処理しているようです。

  • どちらの側でも、既に使用されている参照を割り当てると、参照の他の使用法が自動的に削除されます。(したがって、コンテキストを開いたときにすでに A1 <=> B1 の場合で、次に A1 => B2 と記述した場合、A1 <=> B1 が削除され、A1 <=> B2 が追加されます。あなたはオンです。)
  • 同じ参照を複数回割り当てて重複キーを作成しようとすると、EF は「多重度制約違反」という例外をスローします。(つまり、同じコンテキストで、A1 => B1 と A2 => B1 の両方、または同様の競合するマッピングを記述しました。)
  • DB を手動で更新して重複キーの状況を作成する場合、EF がこれに遭遇すると、「リレーションシップの多重性制約違反が発生しました...これは回復不能なエラーです」という例外がスローされます。

EF6 では、プロパティを外部キー列にマップすることはできないようです (少なくとも Fluent API では)。そうしようとすると、プロパティと関連付けの両方に同じ名前を別々に使用しようとするため、一意でない列名の例外が発生します。

また、2 つの外部キー (つまり、両側に 1 つ) を持つことは技術的に正しくないことにも注意してください。このような配置は、実際には0..1 から 0..1 への 2 つの関連付けになります。これは、両端のキーが一致しなければならないということは何もないためです。これは、UI および/または何らかのデータベース制約を介して、別の方法で関係を強制する場合に機能する可能性があります。

また、0..1 から 0..1 への関連付けが正確に何であるかについて、誤解/誤解がある可能性があることにも気付きました。これが意味することは、私の理解と EF の考え方からすると、両側でオプションの 1 対 1 の関連付けであるということです。したがって、関係のない両側にオブジェクトを持つことができます。(1 対 0..1 の関連付けでは、一方のオブジェクトは関係なしに存在できますが、他方のオブジェクトは関連付けるオブジェクトを常に必要とします。)

しかし、0..1 から 0..1 は、関連付けを一方の方向に移動させ、他方の方向には移動させないという意味ではありません。A1 => B1 の場合、B1 => A1 (A1 <=> B1)。A1 を B1 に関連付けずに、B1 を A1 に割り当てることはできません。これが、この関連付けが単一の外部キーのみを使用できる理由です。一部の人々は、これが正しくない関連付けをしようとしている可能性があると思います (A1 は B1 に関連付けられますが、B1 は A1 には関連付けられません)。しかし、それは実際には 1 つの関連付けではなく、2 つの 0..1 から 0..1 への関連付けです。

于 2021-09-19T20:55:21.513 に答える