首先通过Fluent API在EF代码中实现Zero或One to Zero或One关系

时间:2013-02-05 06:21:10

标签: c# entity-framework ef-code-first entity-relationship fluent

我有两个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; }
    ....   
}

每个订单可以由一个或零引号组成,每个引号可能引起订单,所以我有“一个或零”到“一个或零”关系,我该如何实现这个,在EF Code中首先使用流畅的API?

6 个答案:

答案 0 :(得分:37)

将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

答案 1 :(得分:23)

@ 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

答案 2 :(得分:6)

请参阅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场景中的主体,我认为你不能在Code中首先使用Fluent API。如果他们共享一个密钥,你就可以了。 1:1可选假定从属使用主要密钥。

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

你会很接近。但是如果你想要两者都是外键,EF会抱怨冲突的外键。基本上A取决于B取决于EF不喜欢,即使这些列在数据库上可以为空并且技术上可行。

这里使用此测试程序进行尝试。只需在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.
            ;
    }   
}
}

答案 3 :(得分:5)

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

答案 4 :(得分: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; }
}
     

关键属性

     

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

答案 5 :(得分:0)

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