首先通过Fluent API在EF代码中实现Zero或One to Zero或One关系
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了首先通过Fluent API在EF代码中实现Zero或One to Zero或One关系相关的知识,希望对你有一定的参考价值。
我有两个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代码中首先通过流畅的API实现它?
通过改变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):
特别感谢(Mr. 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场景中的Principal,我认为你不能在Code中首先使用Fluent API。如果他们共享一个密钥,你就可以了。 1:1可选假定从属使用来自Primary的密钥。
但是因为你需要先将一个表保存在另一个表之前。您可以使用代码检查其中一个外键。或者在代码首次创建后将第二个外部添加到数据库。
你会很接近。但是如果你想要两者都是外键,EF会抱怨冲突的外键。本质上,A依赖于B依赖于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.
;
}
}
}
改编自这个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需要共享主键。
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属性用于将其标识为键:
以上是关于首先通过Fluent API在EF代码中实现Zero或One to Zero或One关系的主要内容,如果未能解决你的问题,请参考以下文章
EF6:创建存储过程。使用 Fluent API 或 DBMigrations?