entity framework – 一对一 – ReferentialConstraint映射到商店生成的列

我在EF中创建了一个简单的一对一关系。 但是当我尝试插入时,我收到以下错误:

ReferentialConstraint映射到存储生成的列。 列:’ACCOUNT_ID’。

控制台应用示例:

namespace EF_ConsoleApp_Test { public class Program { public static void Main(string[] args) { var account = new Account { AccountNumber = "00123456", CustomerValue = new Customer { FirstName = "Joe" } }; using (var db = new MainContext()) { db.Accounts.Add(account); db.SaveChanges(); } } } [Serializable] [Table("CUSTOMERS")] public class Customer { [Key] [Column("CUSTOMER_ID")] public int? Id { get; set; } [Required] [Column("FIRST_NAME")] [StringLength(45)] public string FirstName { get; set; } public virtual Account Account { get; set; } public Customer() { } } [Serializable] [Table("ACCOUNTS")] public class Account { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] [Column("ACCOUNT_ID")] public int? Id { get; set; } [Required] [Column("ACCOUNT_NUMBER")] [Display(Name = "Account Number")] [StringLength(16)] public string AccountNumber { get; set; } [Column("CUSTOMER_ID")] public int? CustomerId { get; set; } public virtual Customer CustomerValue { get; set; } ///  /// Default Constructor ///  public Account() { } } internal class MainContext : DbContext { internal MainContext() : base("name=DB.Context") { Database.SetInitializer(null); } public virtual DbSet Accounts { get; set; } public virtual DbSet Customers { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Configure FK modelBuilder.Entity() .HasRequired(c => c.Account) .WithRequiredPrincipal(a => a.CustomerValue); base.OnModelCreating(modelBuilder); } } } 

数据库表创建语句:

 CREATE TABLE [dbo].[CUSTOMERS]( [CUSTOMER_ID] [INT] IDENTITY(1,1) NOT NULL, [FIRST_NAME] [varchar](45) NOT NULL, CONSTRAINT [PK_CUSTOMERS] PRIMARY KEY CLUSTERED ( [CUSTOMER_ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO CREATE TABLE [dbo].[ACCOUNTS]( [ACCOUNT_ID] [INT] IDENTITY(1,1) NOT NULL, [CUSTOMER_ID] [int] NOT NULL, [ACCOUNT_NUMBER] [varchar](16) NOT NULL, CONSTRAINT [PK_ACCOUNTS] PRIMARY KEY CLUSTERED ( [ACCOUNT_ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] ALTER TABLE [dbo].[ACCOUNTS] WITH CHECK ADD CONSTRAINT [FK_ACCOUNTS_CUSTOMERS] FOREIGN KEY([CUSTOMER_ID]) REFERENCES [dbo].[CUSTOMERS] ([CUSTOMER_ID]) GO 

App.config中:

    

我需要做些什么来改变这项工作?

笔记:

  • 我正在使用EF 6.2和.NET 4.7.1。
  • 我inheritance了这个数据库模式,并且无法更改一对一关系。
  • 我试图通过仅调用SaveChanges()来避免显式创建事务,一旦反对包装单独的调用以创建客户,然后是Account。

按照惯例,EF6表示使用所谓的共享主密钥关联的一对一关系,其中从属实体的PK也用作主体实体的FK。

在您的情况下,它将Account.Id视为Customer的FK,并且由于它是自动生成的,因此您会得到相关的exception。

另外一个问题是EF6不支持与显式FK属性的一对一关系(没有类似于一对多关系的HasForeignKey流畅API)。

因此,您需要从模型中删除AccountId属性,并仅保留导航属性。 此外,尽管不是非常必要,但遵循命名约定并将其称为Account而不是AccountValue

换句话说,替换

 [Column("CUSTOMER_ID")] public int? CustomerId { get; set; } public virtual Customer CustomerValue { get; set; } 

 public virtual Customer Customer { get; set; } 

可以使用MapKey fluent API指定FK列名称:

 modelBuilder.Entity() .HasRequired(c => c.Account) .WithRequiredPrincipal(a => a.Customer) .Map(m => m.MapKey("CUSTOMER_ID")); // <-- 

你完成了。

现在,以下内容正确地首先插入一个新Customer ,然后再引用一个引用它的新Account

 var account = new Account { AccountNumber = "00123456", Customer = new Customer { FirstName = "Joe" } }; db.Accounts.Add(account); db.SaveChanges();