抱歉,这个模糊的标题很难用一句话来描述:
我有 2 个实体User
and UserAddress
,其中 User 有 2 个外键DefaultInvoiceAddressId
and DefaultDeliveryAddressId
和 UserAddress 有一个UserId
外键。
用户对象具有默认地址的导航属性(DefaultInvoiceAddress
and DefaultDeliveryAddress
)以及他所有地址的一个:AllAddresses
.
映射等有效,创建和更新用户和地址也有效。
但不起作用的是将用户的现有地址设置为例如默认发票地址。用 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;
}
}
创建新用户地址以及更新地址时都会调用此方法。创建场景按预期工作,但是在更新情况下我收到以下错误:
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.
我使用从数据库检索的 User 对象及其包含的默认传递地址来调用该方法,我通过预先加载将其与其一起加载。
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
简而言之,我只想将用户的 DefaultDeliveryAddress 也设为他的 DefaultInvoiceAddress,这可以使用上面的 SQL Update 命令轻松完成,但我的 EF 代码遗漏了一些内容。
我已经检查过:
- 仅设置了Id,导航属性(
DefaultInvoiceAddress
) 被重置为 null
- UserAddress.UserId = User.Id(显然因为它已经分配给用户)
- 用户对象将变成
Modified
(用调试器检查),因为它的属性之一被标记为已修改
- 我还尝试清除两个默认地址导航属性,但这也没有帮助
我怀疑这个问题是由于 User 实体有 2 个对 UserAddress 的引用,并且两个外键都设置为引用同一个地址 - 我怎样才能让 EF 处理它?
Update:
以下是 User 实体的映射:
// 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 没有返回 User 的导航属性;它只包含 HasMaxLength 和 HasColumnName 设置(我排除它们以保持问题的可读性)。
Update 2
这是 Intellitrace 执行的命令:
The command text "update [TestSchema].[User]
set [DefaultInvoiceAddressId] = @0
where ([Id] = @1)
" was executed on connection "Server=(localdb)\..."
我觉得不错;似乎只有 EF 状态管理器会对键映射感到困惑。