我有User
和Person
實體,使得每個User
必須正好1 Person
相關聯,並且每個Person
可以關聯零或1 User
的實體模型。DbUpdateException與實體不公開外鍵的屬性
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
作爲關係的相關方,並在User
表上放置PersonId (FK, int, not null)
列。我不相信可以在任何一個實體上使用外鍵屬性來幫助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' AssociationSet的關係是在 '刪除' 狀態。考慮到多重性約束,相應的「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
狀態。
我在做什麼錯?
那麼你如何得到這個?我有一個類似的問題,有一個最後一個職位關聯的主題。如果將最後一篇文章設置爲不同的文章,它會嘗試刪除前一篇文章!跆拳道是關於? – leen3o 2012-07-13 08:57:37
這是*關於*時間從EF切換到NHibernate的ORM! J/K ...就我而言,這是因爲多重性的限制。每個用戶**必須擁有一個人,但一個人可以有一個空用戶。當我將Person.User設置爲null時,EF首先檢查約束以查看關係的另一端(User.Person)是否可以設置爲null。由於它不能,EF會將用戶置於已刪除狀態。如果我將User.Person設置爲null,Person將不會**進入已刪除狀態,因爲它可以有0..1個用戶。如果您的約束條件不同,請提出問題,我會看一看。 – danludwig 2012-07-13 13:50:57