假设我有三个主键表为“存储生成模式”。
Table1
和Table2
以一对一的关系与Table3
相关联。这意味着:Table3
只能有一个table1
public partial class table1
{
public int Id { get; set; }
public string name { get; set; }
public virtual Table3 Table3 { get; set; }
}
public partial class table2
{
public int Id { get; set; }
public string name { get; set; }
public virtual Table3 Table3 { get; set; }
}
public partial class Table3
{
public Table3() { }
public Table3(table1 s) { this.table1 = s; this.table2 = null; }
public Table3(table2 t) { this.table2 = t; this.table1 = null; }
public int Id { get; set; }
public string name { get; set; }
public virtual table1 table1 { get; set; }
public virtual table2 table2 { get; set; }
}
控制器
Table1 T1 = new Table1()
{
name = obj.table1.name,
};
db.Students.Add(T1);
db.SaveChanges(); // works sucessfully
// Data in inserted
Table3 t3 = new Table3()
{
name = obj.name,
table1 = T1,
table2 = null
};
db.Users.Add(u); // here error occurs
db.SaveChanges(); //InvalidOperationException:
问题:
在控制器中,当我尝试插入数据库时,插入了Table1
并且Table2
引发了错误:
ReferentialConstraint中的依赖属性映射到存储生成的列。列:'Id'。
为什么会导致此错误?
通常在数据库中,插入外键的Id。但是,在Entity Framework中,您拥有整个表table3.table1.name
的对象。有任何解释可以删除此错误吗?
答案 0 :(得分:1)
EF中整数键的默认约定是在数据库中生成它们,但是在您有1-1关系的情况下,只有主表可以具有数据库生成的键。然后将该密钥重新用作从属实体的密钥。
例如
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp8
{
public partial class Table1
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Table3 Table3 { get; set; }
}
public partial class Table2
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Table3 Table3 { get; set; }
}
public partial class Table3
{
public Table3() { }
public Table3(Table1 s) { this.Table1 = s; this.Table2 = null; }
public Table3(Table2 t) { this.Table2 = t; this.Table1 = null; }
public int Id { get; set; }
public string Name { get; set; }
public virtual Table1 Table1 { get; set; }
public virtual Table2 Table2 { get; set; }
}
class Db : DbContext
{
public DbSet<Table1> Table1 { get; set; }
public DbSet<Table2> Table2 { get; set; }
public DbSet<Table3> Table3 { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Table1>()
.HasOptional(t => t.Table3)
.WithOptionalPrincipal(t1 => t1.Table1);
modelBuilder.Entity<Table2>()
.HasOptional(t => t.Table3)
.WithOptionalDependent(t => t.Table2);
modelBuilder.Entity<Table1>()
.Property(t => t.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Table2>()
.Property(t => t.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<Table3>()
.Property(t => t.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
class Program
{
static void Main(string[] args)
{
using (var db = new Db())
{
Table1 T1 = new Table1()
{
Name = "Foo"
};
db.Table1.Add(T1);
db.SaveChanges(); // works sucessfully
// Data in inserted
Table3 t3 = new Table3()
{
Name = "Bar",
Table1 = T1,
Table2 = null
};
db.Table3.Add(t3);
db.SaveChanges();
var t2 = new Table2()
{
Name = "Baz",
Table3 = t3
};
db.Table2.Add(t2);
db.SaveChanges();
}
}
}
}