这可能是一个重复的问题,但是在标题中搜索单词只会得到很多不相关的结果。
我有一个大致设置如下的实体:
public abstract class A
{
public GUID AId { get; set; }
public string SomeProperty { get; set; }
}
public class B : A
{
public string SomeOtherProperty { get; set; }
}
上下文具有B
对象的public DbSet<B> BInstances { get; set; }
。在OnModelCreating
中,映射A
设置为忽略,B
映射到一个名为TableB
的表。
AId
字段不是自动生成的(不是标识字段(,但它在数据库和映射中都设置为主键。在数据库中,该字段定义为没有默认值的非空uniqueidentifier
。
在运行时,我正在使用其键加载B
的实例(_token
只是一个CancellationToken
(:
var b = await (dbCtx.BInstances.FirstOrDefaultAsync(e => e.AId), _token));
然后,设置b
属性,我尝试将其保存回数据库:
b.SomeOtherProperty = "some new text";
await (dbCtx.SaveChangesAsync(_token));
此时,我从数据库中收到">违反主键约束"错误,指出无法插入AId
的值,因为它是重复的。当然,ID 已经在数据库中,我使用 ID 从那里加载实体。出于某种原因,EF 生成一个 INSERT 语句,而不是 UPDATE,我不明白为什么。
当我检查dbCtx.Entry(b).State
时,它已经设置为EntityState.Modified
.我很茫然 - 有人可以指出我做错了什么吗?我以前从未遇到过更新实体的问题,但我没有将 EF 与 GUID 主键一起使用(通常我使用long
主键(。
我使用的是EF 6和.NET Framework 4.7.1。
谢谢大家的建议 - 事实证明这是我造成的映射问题。
在我的OnModelCreating()
调用中,我在未从基类继承的类型上调用了MapInheritedProperties()
(当然,除了object
( - 这似乎引发了一个问题。共享基类的其他实体在映射调用中工作正常。
我还直接针对实体类调用ToTable()
- 由于我不明白的原因,这破坏了我的表映射。一旦我将该调用移动到Map()
内,它就开始按预期工作。
所以我从这个出发:
entity.ToTable("tablename");
对此:
entity.Map(m => m.ToTable("tablename"));
来解决问题。
希望这对未来的读者有用。
试试这个
b.SomeOtherProperty = "some new text";
dbCtx.BInstances.AddOrUpdate(b);
await (dbCtx.SaveChangesAsync(_token));
AddorUpdate 将更新您的 b 实例(如果已添加(。