【发布时间】:2018-08-16 15:59:07
【问题描述】:
如果我尝试添加一个根本不存在的相关实体,我预计 EF 6.2.0 会失败。但在这种情况下,有问题的相关实体(Person)在 SaveChanges 之前被添加到上下文中(还没有在 Db 中,但我看到在 ChangeManager 中)。 但由于某种原因,EF 告诉我:“INSERT 语句与 FOREIGN KEY 约束 \"FK_AuditPerson_Person\" 冲突。冲突发生在数据库 \"Person\"、表 \"person.Person\"、列 'Id' "
我已经用几个类重现了我的问题:
public class Person
{
public Guid Id { get; set; }
}
还有:
public class AuditPerson
{
public Guid AuditId { get; set; }
public Guid PersonId { get; set; }
public DateTime Timestamp { get; set; }
}
上下文是:
public class PersonTestContext : DbContext
{
public DbSet<Person> Packages { get; set; }
public DbSet<AuditPerson> PersonAudits { get; set; }
public PersonTestContext() : base("PersonTestDb")
{
Database.SetInitializer<PersonTestContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>()
.ToTable("Person", "person")
.HasKey(t => t.Id);
modelBuilder.Entity<AuditPerson>()
.ToTable("AuditPerson", "dbo")
.HasKey(ap => new { ap.AuditId, ap.PersonId });
base.OnModelCreating(modelBuilder);
}
}
问题出现在以下示例中:
static void Main(string[] args)
{
using (var context = new PersonTestContext())
{
var person = new Person { Id = Guid.NewGuid() };
context.Persons.Add(person);
var audit = new AuditPerson { AuditId = Guid.NewGuid(), Timestamp = DateTime.UtcNow, PersonId = package.Id };
context.PersonAudits.Add(audit);
context.SaveChangesAsync().Wait();
}
Console.ReadKey();
}
告诉 EF PersonId 指的是将在同一个 SaveChanges 调用中保存的对象的可用替代方法是什么?
现在,当我添加时,问题就消失了:
public virtual Person Person { get; set; }
到 AuditPerson 类。但是如果没有导航属性,EF 就不能解决这个问题吗?
Db 已经存在并且“FK_AuditPerson_Person”为:
ALTER TABLE [dbo].[AuditPerson] WITH CHECK
ADD CONSTRAINT [FK_AuditPerson_Person]
FOREIGN KEY([PersonId])
REFERENCES [person].[Person] ([Id])
我有一种感觉,我以前见过它在没有导航属性的情况下完成。
最后的想法
正如 Steve 所解释的,EF 不保证插入的顺序。 如果我们使用相同的代码,但类名为 Appointment 而不是 Person,则不会发现任何问题:添加记录时没有任何 FK 冲突。 实际生产代码(现已修复)也是如此。显然 EF 使插入按类名排序(查看代码可以澄清),因此人员插入是在审核之后完成的,但约会是在之前完成的,因此行为差异
【问题讨论】:
-
EF 创建一个属性作为对 Person 对象的引用。在您的示例中,
AuditPerson的属性应为Person,而不是Guid PersonId。然后将新的 Person 分配给它的属性:audit.person = person; -
是的,将 Person 导航属性添加到 AuditPerson。
标签: c# entity-framework entity-framework-6