简体   繁体   English

通过 Fluent API 首先在 EF 代码中实现零或一到零或一的关系

[英]Implementing Zero Or One to Zero Or One relationship in EF Code first by Fluent API

I have two POCO classes:我有两个 POCO 课程:

Order Class:订单类别:

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; }
    ....
}

Quotation Class:报价类:

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; }
    ....   
}
  • Each Order may be made from one or zero quotation, and每个Order可以从一个或零个报价中进行,并且
  • each quotation may cause an order.每个报价都可能导致订单。

So I have an "one or zero" to "one or zero" relation, how can I implement this, in EF Code first by Fluent API?所以我有一个“一或零”到“一或零”的关系,我如何在Fluent API 的EF代码中实现这一点?

By changing pocos to:通过将 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; }
}

and using these mapping files:并使用这些映射文件:

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

we will have this DB(that means 0..1-0..1):我们将拥有这个 DB(这意味着 0..1-0..1):

在此处输入图片说明

with special thanks to ( Mr. Vahid Nasiri )特别感谢 ( Vahid Nasiri 先生)

@Masoud's procedure was: @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"));

It gives:它给:

在此处输入图片说明

By changing the code to:通过将代码更改为:

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

It gives:它给:

在此处输入图片说明

See http://msdn.microsoft.com/en-us/data/jj591620 EF Relationships请参阅http://msdn.microsoft.com/en-us/data/jj591620 EF 关系

An excellent Book http://my.safaribooksonline.com/book/-/9781449317867一本优秀的书http://my.safaribooksonline.com/book/-/9781449317867

Here is a post from developer from Dec 2010. But still relevant http://social.msdn.microsoft.com/Forums/uk/adonetefx/thread/aed3b3f5-c150-4131-a686-1bf547a68804 The above article is a nice summary or the possible combinations here.这是 2010 年 12 月开发人员的帖子。但仍然相关http://social.msdn.microsoft.com/Forums/uk/adonetefx/thread/aed3b3f5-c150-4131-a686-1bf547a68804以上文章是一个很好的总结或这里可能的组合。

A solution where dependant Table has key from Primary table is possible.依赖表具有主表中的键的解决方案是可能的。

If you Want Independent Keys where both are Principals in a PK/FK scenario, i dont think you can do it in Code first with Fluent API.如果您想要在 PK/FK 场景中两者都是主体的独立密钥,我认为您无法使用 Fluent API 在 Code first 中做到这一点。 If they share a Key, You are OK.如果他们共享一个密钥,你就可以了。 1:1 optional assumes the dependent uses the key from Primary. 1:1 可选假设依赖使用来自主要的密钥。

But since you need to save one of the tables before the other.但是因为您需要先保存其中一个表。 You can check one of the Foreign Keys with code.您可以使用代码检查其中一个外键。 OR add teh second Foreign to Database after Code first has created it.或者在 Code first 创建之后将第二个 Foreign 添加到数据库中。

You will get close.你会靠近。 But EF will complain about conflicting Foreign keys if you want both to be Foreign keys.但是如果您希望两者都是外键,EF 会抱怨外键冲突。 Essentially the A depends on B depends A EF doesnt like, even if the columns are nullable and technically possible on the DB.本质上 A 取决于 B 取决于 A EF 不喜欢,即使列可以为空并且在 DB 上在技术上是可行的。

Here use this test program to try it.这里用这个测试程序来试试。 Just comment in an out the Fluent API stuff to try some options.只需在 Fluent API 内容中发表评论即可尝试一些选项。 I could NOT get EF5.0 to work with INDEPENDENT PK/FK 0:1 to 0:1 But of course there are reasonable compromises as discussed.我无法让 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.
            ;
    }   
}
}

Adapted from this answer , try this.改编自这个答案,试试这个。

First, fix your classes:首先,修复您的课程:

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
}

Then use the fluent API like that:然后像这样使用流畅的 API:

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

Basically, for 1:1 or [0/1]:[0/1] relationships, EF needs the primary keys to be shared.基本上,对于 1:1 或 [0/1]:[0/1] 关系,EF 需要共享主键。

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

The Key Attribute关键属性

There's a one-to-zero-or-one relationship between the Instructor and the OfficeAssignment entities. Instructor 和 OfficeAssignment 实体之间存在一对零或一的关系。 An office assignment only exists in relation to the instructor it's assigned to, and therefore its primary key is also its foreign key to the Instructor entity.办公室分配仅与分配给它的讲师相关,因此其主键也是其对 Instructor 实体的外键。 But the Entity Framework can't automatically recognize InstructorID as the primary key of this entity because its name doesn't follow the ID or classnameID naming convention.但是实体框架无法自动将 InstructorID 识别为该实体的主键,因为其名称不遵循 ID 或 classnameID 命名约定。 Therefore, the Key attribute is used to identify it as the key:因此,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 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-应用程序

using DataAnnotations:使用数据注释:

public class Order
{
       [Key]
       public int Id {get; set;}

       public virtual Quotation Quotation { get; set; }
}

public class Quotation
{
     [Key, ForeignKey(nameof(Order))]
     public int Id {get; set;}

     public virtual Order Order { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM