繁体   English   中英

设置一对一关系

[英]Setting one-to-one relationship

如何使用fluent API在Entity Framework的代码优先中正确设置一对一关系?

根模型是Project类。 每个项目仅包含一个报价。 它也可以选择包含一个客户订单。

的历史模型的目的是含有相应的非历史行的快照(当Project被添加,一个新的Project被创建并比复制到一个新ProjectHistorical类,如果它被编辑时,一个新的ProjectHistorical类被创建填充以及已编辑Project数据)。 历史对象应该是AutoMapper友好的。 对于数据库引擎中缺少临时数据库支持的情况,您可以将历史模型视为一种愚蠢,琐碎且幼稚的解决方法。

使用此配置,我遇到以下困难:

  1. CustomerOrdersOffers表及其历史对应项会生成一个Project_Id列。 我没有找到方法如何强制使用Id主键或带注释的ProjectId属性(我更喜欢使用带注释的ProjectId属性)。
  2. ProjectHistoricals表具有生成的CustomerOrder_IdOffer_Id列。 我没有找到方法来强制使用Id列(请注意, Id列不是历史表上的主键)或带注释的CustomerOrderIdOfferId列(在ProjectProjectHistorical类上均是如此;我更喜欢使用带注释的CustomerOrderIdOfferId列)。

我已经尝试了很多搜索,甚至尝试了更多的事情,但是没有任何效果(我本来可以预期)。

我有以下型号:

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

和以下流利的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);

这是实体框架将模型编译到数据库的方式:

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

你可以阅读本教程或退房这个答案在计算器或这个答案在MSDN上。

暂无
暂无

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

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