我正在使用Entity Framework(使用代码优先方法),并使用预期的外键和唯一键约束成功创建数据库。
我有两个模型类:
public class Foo
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public Bar Bar { get; set; }
}
public class Bar
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Index(IsUnique = true), StringLength(512)]
public string Url { get; set; }
}
这个应用程序代码:
var foo = GetData();
using (DatabaseContext db = new DatabaseContext())
{
db.Entry(foo).State = EntityState.Added;
if (foo.Bar != null)
{
var bar = await db.Bar.FirstOrDefaultAsync(x => x.Url == foo.Bar.Url);
if (bar != null)
{
// When I assign an existing entity ...
foo.Bar = bar;
}
}
// ... following exception will be thrown.
await db.SaveChangesAsync();
}
SqlException :无法在对象' dbo.Bar'中插入重复的键行。具有唯一索引' IX_Url'重复键值为(https://api.example.com/rest/v1.0/bar/FD6FAB72-DCE2-47DB-885A-424F3D4A70B6)。 声明已经终止。
我不明白为什么Entity Framework尝试添加导航属性Bar
,即使在从同一DbContext
获取并分配它之后也是如此。类似的StackOverflow问题尚未提供任何有效的解决方案。
请告诉我是否需要提供其他信息。
我是否忘记设置任何EF相关配置或类似的东西?提前谢谢!
答案 0 :(得分:4)
这是因为
db.Entry(foo).State = EntityState.Added;
将foo.Bar
(以及未被上下文跟踪的任何引用实体)标记为Added
。
您应该在添加Foo
实体之前解析引用的实体:
var foo = GetData();
using (DatabaseContext db = new DatabaseContext())
{
// Resolve references
if (foo.Bar != null)
{
var bar = await db.Bar.FirstOrDefaultAsync(x => x.Url == foo.Bar.Url);
if (bar != null)
foo.Bar = bar;
}
// Then add the entity
db.Entry(foo).State = EntityState.Added;
await db.SaveChangesAsync();
}