繁体   English   中英

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

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

我有两个 POCO 课程:

订单类别:

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; }
    ....   
}
  • 每个Order可以从一个或零个报价中进行,并且
  • 每个报价都可能导致订单。

所以我有一个“一或零”到“一或零”的关系,我如何在Fluent API 的EF代码中实现这一点?

通过将 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 先生)

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

它给:

在此处输入图片说明

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

一本优秀的书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 在 Code first 中做到这一点。 如果他们共享一个密钥,你就可以了。 1:1 可选假设依赖使用来自主要的密钥。

但是因为您需要先保存其中一个表。 您可以使用代码检查其中一个外键。 或者在 Code first 创建之后将第二个 Foreign 添加到数据库中。

你会靠近。 但是如果您希望两者都是外键,EF 会抱怨外键冲突。 本质上 A 取决于 B 取决于 A EF 不喜欢,即使列可以为空并且在 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.
            ;
    }   
}
}

改编自这个答案,试试这个。

首先,修复您的课程:

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 需要共享主键。

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 实体之间存在一对零或一的关系。 办公室分配仅与分配给它的讲师相关,因此其主键也是其对 Instructor 实体的外键。 但是实体框架无法自动将 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-应用程序

使用数据注释:

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