我有一个包含User
和Person
个实体的实体模型,因此每个User
必须与1个Person
相关联,并且每个Person
都可以与0或User
相关联。
User (0..1) <-------> (1) Person
关联映射得很流畅。最初我只在Person
方宣布了它:
private class PersonOrm : EntityTypeConfiguration<Person>
{
internal PersonOrm()
{
ToTable(typeof(Person).Name, DbSchemaName.People);
// has zero or one User
HasOptional(p => p.User)
.WithRequired(d => d.Person)
.Map(d => d.MapKey("PersonId"))
.WillCascadeOnDelete(false)
;
由于我遇到此错误,我还向User
方添加了相同的映射:
private class UserOrm : EntityTypeConfiguration<User>
{
internal UserOrm()
{
ToTable(typeof(User).Name, DbSchemaName.Identity);
// has exactly 1 Person
HasRequired(p => p.Person)
.WithOptional(d => d.User)
.Map(d => d.MapKey("PersonId"))
.WillCascadeOnDelete(false);
在应用程序中有一个方案,可以创建新的User
并与现有的Person
相关联。这是我目前遇到困难的地方。 EF正在考虑User
作为关系的依赖方,并在PersonId (FK, int, not null)
表上放置User
列。我不相信可以在任一实体上使用外键属性来帮助EF管理关联(是吗?)。
以下是一些尝试处理该方案的失败代码:
// find out if Person already exists
var person = context.People.SingleOrDefault(p => p.Emails.Any(
e => e.Value.Equals(emailAddress, StringComparison.OrdinalIgnoreCase)));
// find out if User already exists
var user = context.Users.SingleOrDefault(
u => u.Name.Equals(emailAddress, StringComparison.OrdinalIgnoreCase));
if (user == null)
{
user = new User
{
Name = emailAddress,
IsRegistered = isRegistered,
Person = person ?? PersonFactory.Create(emailAddress),
// ignore the PersonFactory.Create, that part works
};
context.Entry(user).State = EntityState.Added;
context.SaveChanges();
}
当person
为空(db中尚不存在)时,此代码正常工作。但是,如果person
不为null(已存在于db中)且user
为null,则代码会尝试创建新的User
并将其与现有Person
关联。在调用SaveChanges()
时,我得到DbUpdateException
:
保存不公开外键的实体时发生错误 他们关系的属性。 EntityEntries属性将 返回null,因为无法将单个实体标识为源 例外。可以在保存时处理异常 通过在实体类型中公开外键属性更容易。看到 InnerException以获取详细信息。
内部例外是:
来自'User_Person'AssociationSet的关系在 '删除'状态。给定多重约束,相应的 'User_Person_Source'也必须处于'已删除'状态。
这对我没有任何意义,因为我不是要删除任何内容,而检查EntityState
和User
的{{1}}会显示Person
处于User
状态,而Added
处于Person
状态。我已覆盖Unchanged
来证明:
SaveChanges()
执行此代码时,不会抛出public override int SaveChanges()
{
var userChanges = ChangeTracker.Entries<User>().Single();
var personChanges = ChangeTracker.Entries<Person>().Single();
if (userChanges.State == EntityState.Deleted)
throw new InvalidOperationException("wtf?");
if (personChanges.State == EntityState.Deleted)
throw new InvalidOperationException("wtf?");
return base.SaveChanges();
}
。同样,InvalidOperationException
处于userChanges
状态,Added
处于personChanges
状态。
我做错了什么?
答案 0 :(得分:6)
我现在觉得自己很蠢。在写完这个仔细的问题后,现在很明显了。
我正在测试的Person
已经存在,并且已经与其他User
建立了User.Name
关联。这就是user
即将出现的原因。将Person.User
属性设置为新User
会导致旧User
处于Deleted
状态。卫生署。
抱歉浪费了你的时间。我会留下这个问题,除非它同意删除它会更好。
答案 1 :(得分:0)
确保您在映射中定义了关系(实体类型配置)
例如:
this.HasRequired(t =&gt; t.QuoteResponse).WithMany(t =&gt; t.QuoteResponseItems).HasForeignKey(d =&gt; d.QuoteResponseID);