很抱歉的含糊不清的標題,這是很難形容這一行:爲什麼在更新外鍵後變成引用約束不一致?
我有2個實體User
和UserAddress
,其中用戶有2個外鍵DefaultInvoiceAddressId
和DefaultDeliveryAddressId
和UserAddress有UserId
外鍵。
用戶對象具有默認地址(DefaultInvoiceAddress
和DefaultDeliveryAddress
)的導航屬性,以及其所有地址爲AllAddresses
的導航屬性。
映射等工程,創建和更新用戶和地址也起作用。
儘管將用戶的現有地址設置爲例如「 DefaultInvoiceAddress。用SQL術語來說,我想要發生的是UPDATE USER SET DefaultInvoiceAddressId = 5 WHERE Id = 3
。
我這個嘗試以下方式:
private void MarkAs(User user, UserAddress address, User.AddressType type) {
if (context.Entry(user).State == EntityState.Detached)
context.Users.Attach(user);
// guess I don't really need this:
if (context.Entry(address).State == EntityState.Detached)
context.UserAddresses.Attach(address);
if (type.HasFlag(User.AddressType.DefaultInvoice)) {
user.DefaultInvoiceAddressId = address.Id;
user.DefaultInvoiceAddress = null;
context.Entry(user).Property(u => u.DefaultInvoiceAddressId).IsModified = true;
}
if (type.HasFlag(User.AddressType.DefaultDelivery)) {
user.DefaultDeliveryAddressId = address.Id;
user.DefaultDeliveryAddress = null;
context.Entry(user).Property(u => u.DefaultDeliveryAddressId).IsModified = true;
}
}
這種方法被稱爲既更新地址時,創建新的UserAddresses時也是如此。在創建方案正常工作,但是在更新情況下,我收到以下錯誤:
The changes to the database were committed successfully,
but an error occurred while updating the object context.
The ObjectContext might be in an inconsistent state.
Inner exception message: A referential integrity constraint violation occurred:
The property values that define the referential constraints are not consistent between principal and dependent objects in the relationship.
我打電話了用戶對象我從數據庫中,它包含了DefaultDeliveryAddress retrive,我通過沿着它加載的方法急切的加載。
var user = mainDb.User.Get(UnitTestData.Users.Martin.Id, User.Include.DefaultAddresses);
var existingAddress = user.DefaultDeliveryAddress;
mainDb.User.Addresses.SetAs(user, existingAddress, User.AddressType.DefaultInvoice))
// the SetAs method verfies input parameters, calls MarkAs and then SaveChanges
簡而言之,我只想讓用戶也是他DefaultInvoiceAddress,這與上面的SQL Update命令很容易完成的DefaultDeliveryAddress,但我很想念我的EF代碼的東西。 我已經檢查了:
- 只有ID設置,導航性能(
DefaultInvoiceAddress
)重新設置爲null - UserAddress.UserId = User.Id(很明顯,因爲它已經被分配給用戶)
- 用戶對象將成爲
Modified
(含調試檢查),因爲它的一個屬性被標記爲修改 - 我也試過清除包括默認地址的導航性能,但是這並沒有幫助
我懷疑這個問題是由於用戶實體有2個UserAddress引用,並且這兩個外鍵都設置爲引用相同的地址 - 我如何才能使用EF來處理這個問題?
更新:
下面是用戶實體的映射:
// from UserMap.cs:
...
Property(t => t.DefaultInvoiceAddressId).HasColumnName("DefaultInvoiceAddressId");
Property(t => t.DefaultDeliveryAddressId).HasColumnName("DefaultDeliveryAddressId");
// Relationships
HasOptional(t => t.DefaultInvoiceAddress)
.WithMany()
.HasForeignKey(t => t.DefaultInvoiceAddressId);
HasOptional(t => t.DefaultDeliveryAddress)
.WithMany()
.HasForeignKey(t => t.DefaultDeliveryAddressId);
HasMany(t => t.AllAddresses)
.WithRequired()
.HasForeignKey(t => t.UserId)
.WillCascadeOnDelete();
UserAddress沒有導航屬性返回到用戶;它只包含HasMaxLength和HasColumnName設置(我排除它們以保持問題的可讀性)。
更新2
下面是從智能跟蹤執行的命令:
The command text "update [TestSchema].[User]
set [DefaultInvoiceAddressId] = @0
where ([Id] = @1)
" was executed on connection "Server=(localdb)\..."
看起來好像沒什麼問題;似乎只有EF狀態管理器被關鍵映射弄糊塗了。
發佈用戶和地址的定義和配置。同時發佈生成的實際SQL狀態。 –
嗯,SELECT可以簡單地從查詢中獲得,但對於UPDATE/INSERT,您需要SQL Mgmt工作室或配置文件(迷你配置文件似乎值得一看)。 –
我發現了一種用Intellitrace獲得聲明的方法,我用命令更新了我的問題。 – enzi