2011-01-03 44 views
15

tôi nhận được lỗi này nếu tôi làm theo các bước sau:Các thành viên 'X' đã được thay đổi không phù hợp với các thành viên hiệp hội 'Y'

  1. Thay đổi sở hữu Y của một đối tượng (một tài sản thực thể liên quan)
  2. Cố gắng gửi thay đổi
  3. Tại thời điểm này giá trị của Y và giá trị của X (khóa cơ bản) không có trong thỏa thuận - LINQ to SQL dường như không đồng bộ hóa những điều này cho đến khi GetChangeSet được gọi.
  4. Lỗi dự kiến ​​xảy ra do một số logic nghiệp vụ hoặc hạn chế mức cơ sở dữ liệu trong quá trình cập nhật.
  5. Tại thời điểm này giá trị của Y tương ứng với X vì GetChangeSet được gọi.
  6. Thay đổi giá trị của Y thành Không có gì (aka null).
  7. Gọi GetChangeSet.

Lỗi xảy ra ở bước cuối cùng vì giá trị của X và giá trị ban đầu của X (được trả về bởi GetOriginalEntityState) khác nhau và giá trị mới không đồng ý với Y? Đó có phải là lý do tại sao? Đây có phải là một lỗi trong LINQ to SQL. Phải là vì tôi không thấy cùng một hành vi nếu tôi thay đổi Y thành giá trị khác (không phải null) thay vì trong bước 5. Cách nào đúng đắn? Tôi có thể thấy một vài cách:

  1. Hủy DataContext khi xảy ra lỗi và rời khỏi giao diện người dùng. Tôi không thích điều này bởi vì sau đó không thể phát hiện xung đột thay đổi coccoin lạc quan. Ngữ cảnh mới không có các giá trị ban đầu trong nó được điền cùng lúc với giao diện người dùng, vì vậy nếu giao diện người dùng có bất kỳ giá trị cũ nào trong đó, chúng sẽ khiến dữ liệu trong cơ sở dữ liệu hoàn nguyên.
  2. Làm mới datacontext (OverwriteCurrent) và để nguyên giao diện người dùng. Tôi không thích điều này vì lý do tương tự như # 1.
  3. Làm mới datacontext (OverwriteCurrent) và điền lại giao diện người dùng. Tôi không thích điều này bởi vì sau đó thông báo lỗi vừa được trình bày cho người dùng không hiển thị cho người dùng lỗi họ đã tạo và cho phép họ sửa lỗi đó. Nó cũng loại bỏ tất cả các thay đổi khác mà người dùng có thể đã thực hiện.
  4. Khi lỗi xảy ra, hãy truy xuất khóa cho Y tương ứng với giá trị gốc của X và đặt lại Y, sau đó gọi hàm GetChangeSet để đồng bộ hóa X (X chỉ đọc hoặc riêng tư để tôi không thể đặt lại khóa đó trực tiếp). Điều này dường như hoạt động, nhưng có vẻ như một hack, và có thể yêu cầu rất nhiều mã cho các lỗi tương tự khác.

Có giải pháp nào tốt hơn không. Đây có phải là thứ cần được báo cáo không?

+0

Bạn có thể làm rõ ý bạn bằng "2. Tại thời điểm này, giá trị của Y và giá trị của X (khóa cơ bản) không đồng ý". Chắc chắn bạn không thay đổi thuộc tính khóa chính của thực thể, nhưng một số trường khác, phải không? –

+0

Phải. Giả sử tôi có một đối tượng Order, và một trong các thuộc tính được gọi là Customer cho biết khách hàng nào đã đặt hàng. Điều này đại diện cho Y. Liên kết đó được thể hiện dưới sự che phủ của một thuộc tính ẩn như _CustomerId. Điều này đại diện cho X. Tôi có thể thay đổi khách hàng được liên kết với đơn đặt hàng. Khách hàng sẽ tham khảo đối tượng Khách hàng mới, nhưng _CustomerId sẽ không phản ánh giá trị _Id của Khách hàng nội bộ cho đến khi GetChangeSet được gọi. – BlueMonkMN

Trả lời

0

Dường như lỗi này đã được cố định trong .NET mới nhất và/hoặc Visual Studio 2010. Các mã được tạo cho các tập tin DBML bây giờ chứa mã để cập nhật cơ bản giá trị chính nước ngoài ngay cả khi thiết lập thuộc tính liên kết thành null:

[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Customer_Order", Storage="_Customer", ThisKey="fkCustomer", OtherKey="id", IsForeignKey=true)] 
    public Customer Customer 
    { 
     get 
     { 
      return this._Customer.Entity; 
     } 
     set 
     { 
      Customer previousValue = this._Customer.Entity; 
      if (((previousValue != value) 
         || (this._Customer.HasLoadedOrAssignedValue == false))) 
      { 
       this.SendPropertyChanging(); 
       if ((previousValue != null)) 
       { 
        this._Customer.Entity = null; 
        previousValue.Orders.Remove(this); 
       } 
       this._Customer.Entity = value; 
       if ((value != null)) 
       { 
        value.Orders.Add(this); 
        this._fkCustomer = value.id; 
       } 
       else 
       { 
        this._fkCustomer = default(Nullable<int>); 
       } 
       this.SendPropertyChanged("Customer"); 
      } 
     } 
    } 

Tôi nghĩ rằng this._fkCustomer = default(Nullable<int>); không được có trong mã tôi đã thử nghiệm khi tôi đăng câu hỏi này lần đầu. Vì vậy, hoặc là tôi đã có DBML của tôi thiết lập sai, hoặc vấn đề này đã được cố định.

0

mỗi MSDN:

Để cập nhật các mối quan hệ, tài liệu tham khảo từ các con cho phụ huynh (có nghĩa là, các tài liệu tham khảo tương ứng với phím nước ngoài) được coi là cơ quan chức năng. Tham chiếu theo hướng ngược lại (có nghĩa là, từ cha mẹ sang con) là tùy chọn. Các lớp quan hệ (EntitySet và EntityRef) đảm bảo rằng các tham chiếu hai chiều nhất quán cho các mối quan hệ một-nhiều và một-một. Nếu mô hình đối tượng không sử dụng EntitySet hoặc EntityRef và nếu tham chiếu ngược lại có mặt, bạn có trách nhiệm giữ cho nó phù hợp với tham chiếu chuyển tiếp khi mối quan hệ được cập nhật.

Nếu bạn cập nhật cả tham chiếu bắt buộc và khóa ngoại tương ứng, bạn phải đảm bảo rằng chúng đồng ý. Một ngoại lệ InvalidOperationException được ném ra nếu cả hai không được đồng bộ hóa tại thời điểm bạn gọi SubmitChanges.Mặc dù thay đổi giá trị khóa ngoại là đủ để ảnh hưởng đến bản cập nhật của hàng bên dưới, bạn nên thay đổi tham chiếu để duy trì kết nối của biểu đồ đối tượng và tính nhất quán hai chiều của các mối quan hệ.

http://msdn.microsoft.com/en-us/library/Bb386982(v=VS.90).aspx

+0

Nói cách khác -> thứ tự hoạt động. Đầu tiên tạo/cập nhật đối tượng khách hàng của bạn và gửi thay đổi. Sau đó tạo đối tượng thứ tự. Đơn đặt hàng liên kết với customerId. gửi thay đổi. – bleepzter

+0

Sự cố không tồn tại khi thiết lập liên kết. Nó tồn tại khi cố gắng xóa nó. Cả hai đối tượng đã có trong cơ sở dữ liệu. Và tôi chưa bao giờ chạm vào khóa ngoại. LINQ-to-SQL không thể giữ nó được đồng bộ hóa trong trường hợp duy nhất có tham chiếu null. Khi tôi cố gắng tách liên kết con khỏi cha mẹ sau khi một lỗi xảy ra, tôi nhận được lỗi này trên GetChangeSet tiếp theo. – BlueMonkMN

0

Gần đây tôi đã gặp phải sự cố này khi sử dụng LINQ to sql, các lớp của tôi được tạo bằng sqlmetal và được hiển thị bằng cách sử dụng các ràng buộc WPF.

Khi hiển thị combox các giá trị từ một bảng Tôi có một tham chiếu khóa ngoài, tôi đã thiết lập SelectedValuePath thành ID. Tuy nhiên khi Id được cập nhật trên hồ sơ của tôi, thành viên được liên kết không được cập nhật để khớp với giá trị Id.

(Address.provID sẽ là 1 và Address.Province sẽ được null)

tôi cập nhật các ràng buộc để cập nhật các SelectedItem và không phải là SelectedValuePath.

<ComboBox Name="provList" DisplayMemberPath="Code" ItemsSource="{Binding Source={x:Static list:GlobalList.ProvinceList}}" SelectedItem="{Binding Path=Provinces}" Width="75" Height="23" HorizontalAlignment="Left" Margin="5,0,0,0" VerticalAlignment="Top"/> 
Các vấn đề liên quan