web-dev-qa-db-ja.com

Fluent APIによる最初のEFコードでのゼロまたは1対0または1の関係の実装

POCOクラスが2つあります

public class Order
{
    int id;
    string code;
    int? quotationId;  //it is foreign key
    public int Id{get;set;}
    public string Code{get;set;}
    public int? QuotationId{get;set;}
    Quotation quotation;
    public virtual Quotation Quotation { get; set; }
    ....
}

public class Quotation
{
    int Id;
    string Code;
    public int Id{get;set;}
    public string Code{get;set;}
    Order order;
    public virtual Order Order { get; set; }
    ....   
}

各注文は1つまたは0つの引用から作成され、各引用mayは注文を引き起こすため、EFで「1または0」と「1または0」の関係があります。これをどのように実装できますかFluent APIによる最初のコードですか?

34
Masoud

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を意味します):

enter image description here

Mr。Vahid Nasiri )に特に感謝します

37
Masoud

@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"));

それは与えます:

enter image description here

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

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

それは与えます:

enter image description here

http://msdn.Microsoft.com/en-us/data/jj59162 EF Relationshipsを参照してください

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

2010年12月の開発者からの投稿を次に示します。しかし、まだ関連性があります http://social.msdn.Microsoft.com/Forums/uk/adonetefx/thread/aed3b3f5-c150-4131-a686-1bf547a68804 上記の記事は、ニースの要約またはここで可能な組み合わせです。

従属テーブルにプライマリテーブルのキーがあるソリューションが可能です。

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

ただし、一方のテーブルをもう一方のテーブルより先に保存する必要があるため。コードで外部キーの1つを確認できます。 OR Codeが最初に作成した後にデータベースに2番目のForeignを追加します。

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

ここで、このテストプログラムを使用して試してください。 Fluent APIをコメントアウトして、いくつかのオプションを試してください。 EF5.0を独立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.
            ;
    }   
}
}
6
phil soady

これから適応 answer 、これを試してください。

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

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は共有されるプライマリキーを必要とします。

5
Moritz
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; }
}

キー属性

インストラクターとOfficeAssignmentエンティティの間には1対0または1の関係があります。オフィスの割り当ては、割り当てられているインストラクターに関連してのみ存在するため、そのプライマリキーは、インストラクターエンティティに対する外部キーでもあります。ただし、Entity Frameworkは、その名前がIDまたはclassnameIDの命名規則に従っていないため、InstructorIDをこのエンティティの主キーとして自動的に認識できません。したがって、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-application

1
astro8891