Xin lỗi vì tiêu đề mơ hồ, thật khó để diễn tả điều này trong một dòng duy nhất:Tại sao trở thành ràng buộc tham chiếu không phù hợp sau khi cập nhật khóa ngoại?
Tôi có 2 thực thể User
và UserAddress
, nơi Người dùng có 2 phím nước ngoài DefaultInvoiceAddressId
và DefaultDeliveryAddressId
và UserAddress có một chìa khóa nước ngoài UserId
.
Đối tượng người dùng có thuộc tính điều hướng cho địa chỉ mặc định (DefaultInvoiceAddress
và DefaultDeliveryAddress
) cũng như một cho tất cả địa chỉ của anh ấy: AllAddresses
.
Việc ánh xạ, vv hoạt động, tạo và cập nhật người dùng và địa chỉ cũng hoạt động.
Điều gì không hoạt động mặc dù đang đặt Địa chỉ của người dùng hiện tại, ví dụ: DefaultInvoiceAddress. Theo thuật ngữ SQL, điều tôi muốn xảy ra là UPDATE USER SET DefaultInvoiceAddressId = 5 WHERE Id = 3
.
Tôi đã thử này theo cách sau:
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;
}
}
Phương pháp này được gọi là cả khi tạo UserAddresses mới cũng như khi cập nhật địa chỉ. Kịch bản tạo các công trình như mong đợi, tuy nhiên trong trường hợp cập nhật tôi nhận được lỗi sau:
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.
tôi gọi là phương pháp với một đối tượng tài khoản tôi retrive từ cơ sở dữ liệu và các DefaultDeliveryAddress nó chứa, mà tôi tải cùng với nó thông qua háo hức tải.
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
Tóm lại, Tôi chỉ muốn làm cho DefaultDeliveryAddress của người dùng cũng DefaultInvoiceAddress của mình, mà sẽ được dễ dàng thực hiện với các lệnh SQL Cập nhật ở trên, nhưng tôi đang thiếu một cái gì đó với mã EF của tôi. Tôi đã kiểm tra rằng:
- Chỉ Id được thiết lập, tài sản chuyển hướng (
DefaultInvoiceAddress
) được tái thiết lập để null - UserAddress.UserId = User.Id (rõ ràng vì nó đã được giao cho người sử dụng)
- Đối tượng sử dụng sẽ trở thành
Modified
(kiểm tra với debugger), kể từ khi một trong những thuộc tính của nó đã được đánh dấu là sửa đổi - tôi cũng đã cố gắng thanh toán bù trừ bất động sản chuyển hướng cả hai địa chỉ mặc định, nhưng điều đó không giúp được gì
Tôi nghi ngờ vấn đề này là do thực thể người dùng có 2 tham chiếu đến UserAddress và cả hai khóa ngoại được đặt để chỉ cùng một địa chỉ - làm cách nào để tôi có thể làm việc với EF?
Cập nhật:
Sau đây là các ánh xạ của thực thể tài:
// 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 không có tính chất định hướng lại cho người dùng; nó chỉ contanis HasMaxLength và HasColumnName cài đặt (tôi loại trừ chúng để giữ cho câu hỏi có phần dễ đọc).
Cập nhật 2
Dưới đây là các lệnh thực thi từ IntelliTrace:
The command text "update [TestSchema].[User]
set [DefaultInvoiceAddressId] = @0
where ([Id] = @1)
" was executed on connection "Server=(localdb)\..."
Hình phạt đối với tôi; dường như chỉ quản lý nhà nước EF bị nhầm lẫn bởi ánh xạ chính.
Đăng định nghĩa và cấu hình Người dùng & Địa chỉ. Đồng thời đăng các đoạn mã SQL thực tế được tạo ra. –
Hmm, lệnh SELECT đơn giản có thể nhận được từ một truy vấn nhưng đối với UPDATE/INSERT bạn sẽ cần đến studio SQL Mgmt hoặc một hồ sơ (profiler nhỏ có vẻ đáng xem). –
Tôi tìm thấy một cách để có được các tuyên bố với Intellitrace, tôi đã cập nhật câu hỏi của tôi với lệnh. – enzi