【发布时间】:2012-04-11 20:19:45
【问题描述】:
我有一个包含User 和Person 实体的实体模型,因此每个User 必须与1 个Person 关联,并且每个Person 可以关联零或1 个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 为空(数据库中尚不存在)时,此代码可以正常工作。但是,当person 不为空(db 中已存在)且user 为空时,代码会尝试创建新的User 并将其与现有的Person 关联。调用SaveChanges() 时,我得到一个DbUpdateException:
保存不公开外键的实体时出错 他们关系的属性。 EntityEntries 属性将 返回 null,因为无法将单个实体标识为源 的例外。可以进行保存时的异常处理 通过在实体类型中公开外键属性更容易。看 InnerException 了解详情。
内部异常是:
“User_Person”关联集中的关系位于 “已删除”状态。给定多重约束,对应的 “User_Person_Source”也必须处于“已删除”状态。
这对我来说没有任何意义,因为我没有尝试删除任何内容,并且检查 User 和 Person 的 EntityState 表明 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 处于 Unchanged 状态。
我做错了什么?
【问题讨论】:
标签: entity-framework entity-framework-4 ef-code-first entity-framework-4.3