dan*_*wig 8 entity-framework entity-framework-4 ef-code-first entity-framework-4.3
我的实体模型User和Person实体,使得每个User必须正好1相关联Person,并且每个Person可以被关联0或1 User.
User (0..1) <-------> (1) Person
Run Code Online (Sandbox Code Playgroud)
该关联可以流畅地映射.最初我只在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)
;
Run Code Online (Sandbox Code Playgroud)
由于我遇到了这个错误,我还在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);
Run Code Online (Sandbox Code Playgroud)
在应用程序中有一个场景,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();
}
Run Code Online (Sandbox Code Playgroud)
当personnull为null 时,此代码工作正常(数据库中尚不存在).但是,如果person不为null(已存在于db中)并且user为null,则代码会尝试创建新的User并将其与现有关联Person.在调用时SaveChanges(),我得到一个DbUpdateException:
保存不公开其关系的外键属性的实体时发生错误.EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源.通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常.有关详细信息,请参阅InnerException.
内在的例外是:
来自'User_Person'AssociationSet的关系处于'已删除'状态.给定多重约束,相应的'User_Person_Source'也必须处于'已删除'状态.
这对我没有任何意义,因为我不是要删除任何东西,并检查EntityState两者User并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();
}
Run Code Online (Sandbox Code Playgroud)
执行此代码时,不会InvalidOperationException抛出任何代码.再次,userChanges处于Added州,并personChanges处于Unchanged州.
我究竟做错了什么?
我现在觉得很蠢.写完这个小心的问题之后,现在很明显了.
在Person我与测试已经存在,并且已经具备了User与不同的关联User.Name.这就是为什么user即将出现的原因.将Person.User属性设置为new User会导致旧User的Deleted状态.卫生署.
抱歉浪费了你的时间.我会留下这个问题,除非它同意删除它会更好.
| 归档时间: |
|
| 查看次数: |
18149 次 |
| 最近记录: |