C# 设置一对一关系
如何先用fluentapi在实体框架的代码中正确设置一对一关系 根模型是项目类。每个项目只包含一个报价。它还可以选择包含一个客户订单 历史模型的目的是在添加项目时包含相应非历史行的快照,创建新项目,然后将其复制到新的ProjectHistorical类中。如果编辑了该类,则创建一个新的ProjectHistorical类,其中填充了已编辑项目的数据。 历史对象应该是自动绘制的。您可以将历史模型看作是在数据库引擎中缺少时态数据库支持的愚蠢、琐碎和天真的解决方案。 使用此配置,我会遇到以下困难: 客户订购并提供表格及其历史记录 对应方生成了一个项目Id列。我找不到办法 如何强制使用Id主键或注释 ProjectId属性我更喜欢使用注释过的ProjectId属性。 ProjectHistoricals表已 已生成CustomerOrder\u Id和Offer\u Id列。我找不到办法 如何强制使用Id列请注意,Id 列不是历史表或注释表上的主键 项目和上的CustomerOrderId和OfferId列 历史课;我更喜欢使用注释的CustomerOrderId和OfferId列。 我已经尝试了很多,甚至尝试了更多的东西,但都没有像我期望的那样奏效 我有以下型号:C# 设置一对一关系,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,如何先用fluentapi在实体框架的代码中正确设置一对一关系 根模型是项目类。每个项目只包含一个报价。它还可以选择包含一个客户订单 历史模型的目的是在添加项目时包含相应非历史行的快照,创建新项目,然后将其复制到新的ProjectHistorical类中。如果编辑了该类,则创建一个新的ProjectHistorical类,其中填充了已编辑项目的数据。 历史对象应该是自动绘制的。您可以将历史模型看作是在数据库引擎中缺少时态数据库支持的愚蠢、琐碎和天真的解决方案。 使用此配置,我会遇到以下困难: 客
public class Project
{
public virtual int Id { get; set; }
// public virtual int OfferId { get; set; }
public virtual Offer Offer { get; set; }
// public virtual int? CustomerOrderId { get; set; }
public virtual CustomerOrder CustomerOrder { get; set; }
}
public class ProjectHistorical
{
public virtual int LogId { get; set; }
public virtual int Id { get; set; }
// public virtual int OfferId { get; set; }
public virtual Offer Offer { get; set; }
// public virtual int? CustomerOrderId { get; set; }
public virtual CustomerOrder CustomerOrder { get; set; }
}
public class CustomerOrder
{
public virtual int Id { get; set; }
// public virtual int ProjectId { get; set; }
public virtual Project Project { get; set; }
}
public class CustomerOrderHistorical
{
public virtual int LogId { get; set; }
public virtual int Id { get; set; }
// public virtual int ProjectId { get; set; }
public virtual Project Project { get; set; }
}
public class Offer
{
public virtual int Id { get; set; }
// public virtual int ProjectId { get; set; }
public virtual Project Project { get; set; }
}
public class OfferHistorical
{
public virtual int LogId { get; set; }
public virtual int Id { get; set; }
// public virtual int ProjectId { get; set; }
public virtual Project Project { get; set; }
}
以下fluent api主键必须始终命名为Id,因为所有模型都实现了一个共享接口,而不是应用程序的通用部分所使用的接口:
modelBuilder.Conventions.Remove<IdKeyDiscoveryConvention>();
modelBuilder.Conventions.Remove<ForeignKeyAssociationMultiplicityConvention>();
modelBuilder.Conventions.Remove<PrimaryKeyNameForeignKeyDiscoveryConvention>();
modelBuilder.Conventions.Remove<OneToOneConstraintIntroductionConvention>();
modelBuilder.Conventions.Remove<TypeNameForeignKeyDiscoveryConvention>();
modelBuilder.Conventions.Remove<AssociationInverseDiscoveryConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<CustomerOrder>().HasKey(t => t.Id);
modelBuilder.Entity<CustomerOrderHistorical>().HasKey(t => t.LogId);
modelBuilder.Entity<CustomerOrderHistorical>().HasRequired(t => t.Project);
modelBuilder.Entity<Offer>().HasKey(t => t.Id);
modelBuilder.Entity<OfferHistorical>().HasKey(t => t.LogId);
modelBuilder.Entity<OfferHistorical>().HasRequired(t => t.Project);
modelBuilder.Entity<Project>().HasKey(t => t.Id);
modelBuilder.Entity<Project>().HasRequired(t => t.Offer).WithRequiredPrincipal(t => t.Project);
modelBuilder.Entity<Project>().HasOptional(t => t.CustomerOrder).WithRequired(t => t.Project);
modelBuilder.Entity<ProjectHistorical>().HasKey(t => t.LogId);
modelBuilder.Entity<ProjectHistorical>().HasRequired(t => t.Offer);
modelBuilder.Entity<ProjectHistorical>().HasOptional(t => t.CustomerOrder);
您可以在stackoverflow或MSDN上读取或签出数据。您的数据模型正确吗?一对一的关系通常意味着两个表应该合并到一个表中。我知道从理论角度来看这应该是相同的。然而,从商业角度来看,项目、报价和客户订单是截然不同的。您可以想象项目是一个包含多个文档的文件夹。另一种想象是,项目是一个工作流,其他模型的存在表明,在流程中的哪一步,首先,您向客户创建报价,然后您收到客户的订单,然后您……谢谢。我之前已经看过两篇链接文章,但我会检查第二篇。PS:最后一个链接不是关于stackoverflow的答案。如果我正确理解了第二个链接,特别是引用的文章,EF至少在版本4.1中不合理地支持一对一关系,因此我需要坚持我已经做过的一对多关系作为解决方法。还是我的理解错了?EF5/EF6中对此没有任何变化?附:问题中没有说明。我的模型的主键需要在每个实体中命名为Id。正确。坚持你的变通方法。我们也在采取一种变通办法:
CreateTable(
"dbo.CustomerOrderHistoricals",
c => new
{
LogId = c.Int(nullable: false, identity: true),
Id = c.Int(nullable: false),
Project_Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.LogId)
.ForeignKey("dbo.Projects", t => t.Project_Id)
.Index(t => t.Project_Id);
CreateTable(
"dbo.Projects",
c => new
{
Id = c.Int(nullable: false, identity: true),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.CustomerOrders",
c => new
{
Id = c.Int(nullable: false, identity: true),
Project_Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Projects", t => t.Project_Id)
.Index(t => t.Project_Id);
CreateTable(
"dbo.Offers",
c => new
{
Id = c.Int(nullable: false, identity: true),
Project_Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Projects", t => t.Project_Id)
.Index(t => t.Project_Id);
CreateTable(
"dbo.OfferHistoricals",
c => new
{
LogId = c.Int(nullable: false, identity: true),
Id = c.Int(nullable: false),
Project_Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.LogId)
.ForeignKey("dbo.Projects", t => t.Project_Id)
.Index(t => t.Project_Id);
CreateTable(
"dbo.ProjectHistoricals",
c => new
{
LogId = c.Int(nullable: false, identity: true),
Id = c.Int(nullable: false),
CustomerOrder_Id = c.Int(),
Offer_Id = c.Int(nullable: false),
})
.PrimaryKey(t => t.LogId)
.ForeignKey("dbo.CustomerOrders", t => t.CustomerOrder_Id)
.ForeignKey("dbo.Offers", t => t.Offer_Id)
.Index(t => t.CustomerOrder_Id)
.Index(t => t.Offer_Id);