7

trong ứng dụng ASP.NET MVC của tôi, tôi đã tách mô hình miền khỏi mô hình khung nhìn.
Tôi biến đổi thực thể của mình thành một đối tượng dạng xem, vì vậy tôi có thể "cung cấp" chế độ xem của mình chỉ với dữ liệu cần thiết (tôi đã sử dụng giá trị cho mục đích này).
Trong quá trình lưu, bộ điều khiển của tôi sẽ quay trở lại đối tượng viewmodel, biến nó thành một thực thể mô hình miền và cố gắng giữ nó với SaveOrUpdate. Tôi nhận thấy rằng nếu tôi cố gắng cập nhật một bản ghi hiện có, Nhibernate coi nó là một đối tượng mới và tạo một INSERT, ngay cả khi thực thể của tôi có một ID thích hợp.
Tôi chưa tải (Nhận/Tải) thực thể trước nguyên nhân tôi muốn tránh ánh xạ lại tất cả các trường.
Tôi có làm gì sai không? Cách tốt nhất để đạt được điều đó là gì?Tôi có phải tải/Nhận thực thể trước khi SaveOrUpdate trong Nhibernate không?

***** - CẬP NHẬT - ***

điều khiển của tôi nhận được một tài khoản (ViewModel), xác nhận nó và cố gắng để lưu nó thông qua một lớp dịch vụ như một thực thể:

public ActionResult Edit(Guid id, Models.User User) 
{ 
... 
var user = new Domain.User(); 
user.InjectFrom(User); 
user.SetId(id); 

user = this._SecurityService.SaveUser(user); 

} 

Đây là dịch vụ:

public Domain.User SaveUser(Domain.User User) 
     { 
      bool Result = false; 

      if (this._ValidationEngine.IsValid(User)) 
      { 
       using (_UnitOfWork) 
       { 
        if (User.Code != Guid.Empty) 
        { 
         var user = this._UserRepository.Load(User.Code); 
         user.InjectFrom(User); 
         User = this._UserRepository.Update(user); 
        } 
        else { 
         User = this._UserRepository.Save(User); 
        } 
        Result = _UnitOfWork.Commit(); 
       } 
      } 
      return (User); 
     } 

Tôi lo ngại về việc tôi phải chuyển đổi chế độ xem/thực thể của mình rất nhiều lần. Bây giờ khi tôi cố gắng lưu một Người dùng mới, tôi nhận được thông báo này: Hàng đã được cập nhật hoặc xóa bởi một giao dịch khác (hoặc bản đồ giá trị chưa được lưu không chính xác)
Có thể đây là một số cách liên quan đến những gì Darin đang nói với tôi.
Có cách nào tốt hơn để làm những gì tôi đang cố gắng làm không?

CẬP NHẬT

tôi đã nhận thấy rằng lỗi "Row đã được cập nhật hoặc xóa ..." là do thực tế là tôi có một phiên bản định nghĩa cho các ánh xạ của tôi. Điều tôi có thể hiểu là tôi cần có Idphiên bản khớp với pháp nhân mà tôi muốn cập nhật.
Tôi muốn hiểu cách người khác làm những việc này với DDD + ASP.NET MVC + NHibernate ???

SOLUTION

Tất cả các đơn vị của tôi có một phiên bản được xác định (tôi quên nói, xin lỗi):

<version name="Version" type="System.Int32" unsaved-value="0"> 
    <column name="Version" not-null="true" /> 
</version> 

Như Ayende giải thích here, Nhibernate cố gắng cập nhật thực thể của tôi với một truy vấn như thế này :

UPDATE Table SET field1 = 'bla', Version = (y+1) WHERE id = x AND Version = y 

trong đó y phải là phiên bản của pháp nhân của tôi. Vì tôi đã không cư trú thực thể của tôi với một phiên bản, nó sẽ tạo ra một ngoại lệ StaleObjectException.
Tôi đã thêm trường phiên bản vào chế độ xem của mình. Tôi lưu nó trong một lĩnh vực ẩn của quan điểm của tôi cùng với id.
Bộ điều khiển của tôi hiện nhận được một mô hình chế độ xem có Id và phiên bản. tôi tiêm các trường này trong thực thể tên miền của tôi và để cho các kho lưu nó (Tôi không reload thực thể của tôi):

User = this._UserRepository.Update(user); 

Nếu tôi nhận được một StaleObjectException ngoại lệ nó có nghĩa là ai đó đã được cập nhật hàng DB và tôi sẽ cung cấp cho người dùng một số phản hồi.

+0

hãy thử tải đối tượng và sau khi tái bản đồ (tôi biết bạn không muốn theo cách này), chỉ cần thử cách này và cho chúng tôi biết nếu nó hoạt động theo cách này – Omu

+0

Tôi đoán vấn đề của tôi là với phiên bản.I've có được xác định trong ánh xạ của tôi. Để tìm một cách tốt hơn để làm điều này – LeftyX

Trả lời

0

Vì bạn đã có Id và, do đó, hãy biết đây là bản cập nhật, hãy sử dụng session.Update thay vì SaveOrUpdate.

+0

Tôi sợ tôi không thể làm điều đó vì nếu tôi cố gắng lưu thực thể của mình, tôi nhận được thông báo này: một đối tượng khác có cùng giá trị số nhận dạng đã được liên kết với phiên: caedb8a4-abce-4c6f-b171-9e7200cc7a37, của pháp nhân : BpReminders.Domain.User – LeftyX

+0

Điều đó có nghĩa là đối tượng đã được tải. Tại sao bạn không cập nhật đối tượng đã tải sau đó? –

+0

xin lỗi đó là một sai lầm. Những gì tôi đang làm bây giờ đang tải một thực thể từ kho lưu trữ và kết hợp nó với một thực thể thu được từ bộ điều khiển. Tôi vẫn gặp lỗi "Hàng đã được cập nhật hoặc xóa bởi một giao dịch khác (hoặc ánh xạ giá trị chưa được lưu là không chính xác)" khi tôi cố gắng chèn. Tôi sẽ cập nhật câu hỏi ban đầu của mình với nhiều thông tin hơn. – LeftyX

4

Để SaveOrUpdate hoạt động như mong đợi, bạn cần chỉ định rõ thuộc tính unsaved-value trên ánh xạ <id> của mình. Vì vậy, ví dụ bạn sẽ phải:

<id unsaved-value="0" ... 

và sau đó phát hành một cuộc gọi SaveOrUpdate trên một mô hình trong đó có các tài sản Id gán cho một giá trị khác nhau hơn 0 và nó sẽ UPDATE thay vì INSERT. Vì vậy, để trả lời câu hỏi của bạn, không, bạn không cần phải tự phát hành SELECT trước UPDATE. SaveOrUpdate nên làm điều này đằng sau hậu trường.

+0

Cảm ơn Daring.Tôi đoán rằng tôi phải sử dụng một Guid trống (00000000-0000-0000-0000-000000000000) nếu id của tôi là loại Guid, phải không? – LeftyX

+0

@vandalo, hãy thử điều này: 'unsaved-value =" 00000000-0000-0000-0000-000000000000 "' (chưa được kiểm tra) –

+0

Cảm ơn, một lần nữa. Bạn sẽ làm gì, dù sao? Tôi có nên tải thực thể từ DB và điền vào mỗi trường với thực thể mới in ca Tôi đang cố gắng cập nhật? Có bất kỳ thực hành tốt nhất nào không? Cảm ơn một lần nữa vì sự giúp đỡ của bạn. – LeftyX

Các vấn đề liên quan