2012-07-03 25 views
9

Trong một dự án ASP.NET MVC, chúng tôi đang sử dụng AutoMapper để ánh xạ từ mô hình miền sang viewmodel - và đôi khi cũng làm phẳng một hệ thống phân cấp trong khi làm như vậy. Điều này làm việc giống như một sự quyến rũ và làm cho logic dựng hình của quan điểm của chúng tôi rất gọn gàng và đơn giản.Làm thế nào để thay đổi editmodel/postmodel thành mô hình miền

Sự nhầm lẫn bắt đầu khi chúng tôi muốn đi theo cách khác từ chế độ xem (hoặc postmodel hoặc editmodel) sang mô hình miền, đặc biệt là khi cập nhật đối tượng. Chúng ta không thể sử dụng tự động/lập bản đồ hai chiều vì:

  1. chúng ta sẽ phải xẹp lún hệ thống phân cấp dẹt
  2. tất cả các thuộc tính trên mô hình miền sẽ phải có thể thay đổi/có setters công
  3. những thay đổi đến từ chế độ xem không phải lúc nào cũng chỉ là các thuộc tính phẳng được ánh xạ trở lại miền, nhưng đôi khi cần gọi các phương thức như "ChangeManagerForEmployee()" hoặc tương tự.

này cũng được mô tả trong bài viết Jimmy Bogards: The case for two-way mapping in AutoMapper, nhưng giải pháp này không được mô tả một cách chi tiết, duy nhất mà họ đi:

Từ EditModel để CommandMessages - đi từ loosely- đã nhập Chỉnh sửaMô hình thành các tin nhắn được nhập mạnh mẽ, được chia nhỏ. Một EditModel có thể tạo ra một nửa tá tin nhắn.

Trong một tương tự SO question có một câu trả lời bằng Mark Seeman nơi ông đề cập rằng

Chúng tôi sử dụng người vẽ bản đồ và dịch vụ trừu tượng để ánh xạ một PostModel đến một đối tượng tên miền

nhưng các chi tiết - việc triển khai khái niệm và kỹ thuật - bị bỏ qua.

ý tưởng của chúng tôi ngay bây giờ là:

  1. nhận được một FormCollection trong phương pháp hành động của bộ điều khiển
  2. Lấy mô hình miền gốc và làm phẳng nó để viewModelOriginal và viewModelUpdated
  3. sáp nhập FormCollection vào viewModelUpdated sử dụng UpdateModel()
  4. Sử dụng một số phương pháp trợ giúp chung để so sánh viewModelOriginal với chế độ xemModelUpdated
  5. Hoặc A) Tạo CommandMessages a la Jimmy Bogard hoặc B) Biến đổi sự khác biệt trực tiếp vào mô hình miền thông qua các thuộc tính và phương pháp (có thể lập bản đồ 1-1 thuộc tính trực tiếp thông qua AutoMapper)

Ai đó có thể cung cấp một số ví dụ về cách họ đến từ FormCollection qua editmodel/postmodel đến mô hình miền? "CommandMessages" hoặc "trừu tượng bản đồ và dịch vụ"?

+1

Tôi sẽ đưa ra câu hỏi này một nghìn phiếu bầu nếu tôi có thể. Tôi đã tìm kiếm vô tận để có một câu trả lời chắc chắn cho điều này. – devuxer

+0

Bạn đã làm gì với quá trình cuối cùng? –

+0

Xin chào Tom. Chúng tôi đã kết thúc bằng cách sử dụng một hỗn hợp và giải pháp phù hợp, nơi chúng tôi 1. Lấy đối tượng Dom từ DAL/DB, 2. flatten Dom đối tượng để ViewModel, 3. sử dụng TryUpdateModel với FormColl trên ViewModel, 4.sử dụng AutoMapper để thực hiện ánh xạ ngược từ khung nhìn phẳng đến Dom (Hierarchy) trên các thuộc tính đơn giản và 5. sử dụng một dịch vụ để ánh xạ các thuộc tính không tầm thường từ viewmodel đến các phương thức Dom (đối tượng Dom và/hoặc Dom Service). Hy vọng điều này sẽ giúp - tôi không chắc câu trả lời nào để đánh dấu là chính xác, vì nó kết hợp nhiều hơn một ...? –

Trả lời

1

tôi sử dụng mô hình sau:

[HttpPost] 
public ActionResult Update(UpdateProductViewModel viewModel) 
{ 
    // fetch the domain model that we want to update 
    Product product = repository.Get(viewModel.Id); 

    // Use AutoMapper to update only the properties of this domain model 
    // that are also part of the view model and leave the other properties unchanged 
    AutoMapper.Map<UpdateProductViewModel, Product>(viewModel, product); 

    // Pass the domain model with updated properties to the DAL 
    repository.Update(product); 

    return RedirectToAction("Success"); 
} 
+0

Xin chào Darin, cảm ơn câu trả lời của bạn, nhưng tôi đang tìm cách biến đổi/dịch mô hình view phẳng thành phân cấp mô hình miền/tổng hợp không chỉ thông qua ánh xạ/thuộc tính mà còn sử dụng các phương thức. –

+0

Dường như mẫu này sẽ dẫn đến ánh xạ không rõ ràng đối với đối tượng miền. – Artyom

1

Bạn có thể muốn xem xét CQRS (Command Query Trách nhiệm Tách riêng - Tôi nghĩ rằng đây có thể là khái niệm bạn bị mất tích), thậm chí có thể với sự kiện Sourcing. Về cơ bản nó là một thực hành tách logic của việc đọc từ một nguồn dữ liệu và ghi vào một nguồn dữ liệu, thậm chí có thể có nghĩa là có các mô hình dữ liệu khác nhau để đọc và viết.

Đây có thể là một nơi tốt để bắt đầu: http://abdullin.com/cqrs/

+0

Hi Pawel, thx Tôi đã nhìn vào CGRS trước đó, có lẽ tôi sẽ xem xét lại nó. Tôi đã có một số ý tưởng về cách tách logic, nhưng tôi đặc biệt đang tìm cách dịch FormCollection/EditModel sang Mô hình miền có thể thông qua các thông báo lệnh, nhưng làm cách nào để biết được thông điệp nào cần tạo? Hoặc nếu thực hiện các dịch vụ (những người lập bản đồ trừu tượng) làm thế nào để tôi biết những gì đã thay đổi? EditModel của tôi chỉ chứa kết quả của các thay đổi, chứ không phải chính các thay đổi/thông báo. –

+0

Cách tôi hiểu tình huống của bạn là: Trong giao diện người dùng, bạn có một biểu mẫu lớn, có 20 trường và giá trị được nhập nhưng bạn không biết cái nào khi bạn gửi tất cả giá trị trở lại máy chủ (sau khi người dùng nhấn "Lưu"). Làm thế nào tôi sẽ tiếp cận nó, cố gắng để đạt được lệnh tách/truy vấn, là tôi muốn chia "Save" hành động vào lệnh (lệnh đến từ giao diện người dùng). Trong thực tế, điều đó có nghĩa là chỉ gửi lại các trường đã bị thay đổi. Và tôi không nghĩ rằng tôi sẽ ràng buộc các giá trị trở lại mô hình khung nhìn mà chỉ xem chúng như một danh sách các lệnh. –

+0

Đúng vậy, tôi có một mẫu chỉnh sửa lớn được điền vào bằng kiểu xem phẳng. Khi người dùng chỉnh sửa và đăng biểu mẫu trở lại bộ điều khiển, tôi không thể thấy trường nào đã bị thay đổi. Ý tưởng của tôi là so sánh một tập hợp các chế độ xem "Trước" và "Sau" (_bản gốc đã được điền và cập nhật là các giá trị bài đăng gốc + sáp nhập trough UpdateModel_) và sau đó tạo các lệnh từ đó (phía máy chủ). Vì vậy, tôi đoán nó phụ thuộc vào những gì bạn có nghĩa là bởi "UI": UI như trong JS phía khách hàng hoặc giao diện người dùng như ở phía máy chủ xem + điều khiển? –

0

Lựa chọn C: Đặt nó tất cả trong hành động điều khiển. Tiếp theo, nếu đó là lông, phân hủy thành dịch vụ (trừu tượng lập bản đồ) hoặc tin nhắn-as-phương pháp (cách thông báo lệnh).

lệnh nhắn cách:

public ActionResult Save(FooSaveModel model) { 
    MessageBroker.Process(model); 

    return RedirectToAction("List"); 
} 

Và bộ vi xử lý:

public class FooSaveModelProcessor : IMessageHandler<FooSaveModel> { 

    public void Process(FooSaveModel message) { 
     // Message handling logic here 
    } 

} 

Đây thực sự là chỉ là về cách di chuyển "chế biến" của mẫu ra khỏi controller action và vào, xử lý chuyên dụng cá nhân .

Nhưng, tôi chỉ thực sự đi tuyến đường này nếu các hành động của bộ điều khiển bị lỗi. Nếu không, chỉ cần lấy biểu mẫu và thực hiện các cập nhật thích hợp đối với các mô hình miền khi cần thiết.

+0

Xin chào Jimmy, thx cho câu trả lời của bạn. Tôi chắc chắn không cố gắng để có được những thứ để lông và giữ bộ điều khiển của tôi nhẹ như trong [ASP.NET MVC 4 trong hành động] (http://manning.com/palermo3/). Tôi cũng đã xem xét các thông báo lệnh (ví dụ: [here] (http://codebetter.com/iancooper/2011/04/27/why-use-the-command-processor-pattern-in-the-service-layer /) và "Sử dụng một ứng dụng xe buýt" trong cuốn sách), nhưng làm thế nào để bạn biết những gì đã thay đổi trong FooSaveModel của bạn? Trong những ngày cũ của webforms tôi sẽ có một sự kiện SelectedIndexChanged từ trình đơn thả xuống CurrentManager của tôi. Bây giờ tôi chỉ có kết quả cuối cùng trong FooSaveModel? –

+0

Jimmy, việc bạn triển khai 'Quy trình (thông điệp FooSaveModel) 'có tương tự như [đề xuất tôi đã thực hiện cho Pawel] hay không (http://stackoverflow.com/questions/11313822/how-to-mutate-editmodel-postmodel-to- domain-model # comment14932448_11320582)? Đó là, bạn không thực sự nhìn vào "trước" và "sau" savemodels để xem những gì đã thay đổi, nhưng thay vì so sánh và ánh xạ SaveModel trực tiếp tới DomainModel, tùy chọn gọi các phương thức nếu cần (ví dụ: 'ChangeManager()')? –

+0

Tại sao bạn cần phải quan tâm những gì đã thay đổi hay không? Nếu tôi quan tâm đến các trường cụ thể đang được thay đổi, điều đó có thể cho thấy rằng tôi cần nhiều màn hình hơn với giao diện công việc cụ thể (và xác thực). Ví dụ: –

0

Có một số điểm tương đồng ở đây với những gì tôi đã làm. Cấu trúc phân cấp của tôi chỉ được làm phẳng từ các đối tượng miền tương đương, nhưng tôi phải đối phó với việc gọi các phương thức dịch vụ rõ ràng trên lưu để làm những việc như thêm vào bộ sưu tập con, thay đổi các giá trị quan trọng, chứ không phải là ánh xạ ngược. Tôi cũng phải so sánh trước và sau khi chụp nhanh.

Lưu của tôi là Ajax được đăng dưới dạng JSON vào một hành động MVC và nhập hành động đó trở lại với cấu trúc mô hình khung nhìn bởi MVC. Sau đó, tôi sử dụng AutoMapper để chuyển đổi mô hình chế độ xem cấp cao nhất và con cháu của nó trở lại cấu trúc miền tương đương của nó. Tôi đã định nghĩa một số tùy chỉnh AutoMapper ITypeConverters cho những trường hợp mà một mục con mới đã được thêm vào máy khách (tôi đang sử dụng Knockout.js) và tôi cần gọi một phương thức dịch vụ rõ ràng. Một cái gì đó như:

  foreach (ChildViewModel childVM in viewModel.Children) 
     { 
      ChildDomainObject childDO = domainObject.Children.Where(cdo => cdo.ID.Equals(childVM.ID))).SingleOrDefault(); 
      if (childDO != null) 
      { 
       Mapper.Map<ChildViewModel, ChildDomainObject>(childVM, childDO); 
      } 
      else 
      { 
       MyService.CreateChildDO(someData, domainObject); // Supplying parent 
      } 
     } 

Tôi làm điều tương tự cho quá trình xóa và quá trình này khá độc đáo qua toàn bộ cấu trúc. Tôi đoán một cấu trúc phẳng có thể là dễ dàng hơn để làm việc với hoặc khó hơn - Tôi có một AbstractDomainViewModel với một ID mà tôi làm phù hợp ở trên, giúp.

Tôi cần so sánh trước và sau khi cập nhật vì lớp dịch vụ của tôi gọi xác thực kích hoạt có thể ảnh hưởng đến các phần khác của đồ thị đối tượng và điều này quy định JSON cần trở lại như phản hồi Ajax. Tôi chỉ quan tâm đến những thay đổi có liên quan đến giao diện người dùng, vì vậy tôi chuyển đối tượng miền đã lưu trở lại mô hình chế độ xem mới và sau đó có phương thức trợ giúp để so sánh 2 mô hình chế độ xem, sử dụng kết hợp kiểm tra và phản chiếu trả trước thủ công.

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