20

Trong web method của tôi, tôi nhận được một đối tượng của một số bên thứ ba C# lớp thực thể. Lớp thực thể không là gì ngoài số DataContract. Lớp thực thể này khá phức tạp và có các thuộc tính của các kiểu khác nhau, một số thuộc tính cũng là các bộ sưu tập. Tất nhiên, những loại liên kết này cũng là DataContracts.LINQ to Xml VS XmlSerializer VS DataContractSerializer

Tôi muốn tuần tự hóa thực thể DataContract đó thành XML như một phần của logic nghiệp vụ của dịch vụ web của tôi. Tôi không thể sử dụng trực tiếp DataContractSerializer (đối tượng tôi nhận được trong phương thức web) đơn giản vì lược đồ XML hoàn toàn khác nhau. Vì vậy, XML được tạo ra bởi DataContractSerializer sẽ không được xác nhận đối với lược đồ.

Tôi không thể kết luận cách tiếp cận mà tôi nên tuân theo để triển khai. Tôi có thể nghĩ ra phương pháp thực hiện như sau:

  1. LINQ to XML - Điều này có vẻ ok nhưng tôi cần phải tạo ra cây XML (ví dụ: các yếu tố hoặc đại diện XML của dụ lớp) bằng tay đối với từng loại đối tượng. Vì có nhiều lớp thực thể và chúng được liên kết với nhau, tôi nghĩ rằng đây là quá nhiều công việc để viết các phần tử XML theo cách thủ công. Bên cạnh đó, tôi sẽ phải tiếp tục sửa đổi cây XML và khi lớp thực thể giới thiệu một số thuộc tính mới. Không chỉ điều này, mã mà tôi tạo ra cây XML sẽ trông hơi vụng về (ít nhất là về ngoại hình) và sẽ khó duy trì/thay đổi bởi một số nhà phát triển khác trong tương lai; anh ta/cô ấy sẽ phải xem xét nó rất chặt chẽ để hiểu cách XML được tạo ra.

  2. XmlSerializer - Tôi có thể viết các lớp thực thể riêng của mình đại diện cho cấu trúc XML mà tôi muốn. Bây giờ, tôi cần phải sao chép chi tiết từ đối tượng đến đối tượng của các lớp của riêng tôi. Vì vậy, đây là công việc bổ sung (cho .NET quá khi thực thi mã!). Sau đó, tôi có thể sử dụng XmlSerializer trên đối tượng của mình để tạo XML. Trong trường hợp này, tôi sẽ phải tạo các lớp thực thể và bất cứ khi nào thực thể bên thứ ba được sửa đổi, tôi sẽ phải thêm thuộc tính mới trong lớp của tôi. (với các thuộc tính XmlElement hoặc XmlAttibute). Nhưng mọi người khuyên bạn nên DataContractSerializer trong phần này và vì vậy tôi không muốn hoàn thành việc này trừ khi tất cả các khía cạnh đều rõ ràng với tôi.

  3. DataContractSerializer - Một lần nữa, tôi sẽ phải viết lớp thực thể của riêng mình vì tôi không kiểm soát được DataContracts của bên thứ ba. Và tôi cần phải sao chép chi tiết từ đối tượng đến đối tượng của các lớp học của riêng tôi. Đây là công việc bổ sung. Tuy nhiên, vì DataContractSerializer không hỗ trợ các thuộc tính Xml, tôi sẽ phải triển khai IXmlSerializable và tạo Xml theo yêu cầu trong phương thức WriteXml. DataContractSerializer nhanh hơn XmlSerializer, nhưng một lần nữa tôi sẽ phải xử lý các thay đổi (trong WriteXml) nếu thực thể của bên thứ ba thay đổi.

Câu hỏi:

  • phương pháp nào là tốt nhất trong kịch bản này xem xét hiệu suất quá?
  • Bạn có thể đề xuất một số cách tiếp cận tốt hơn không?
  • Có phải xem xét DataContractSerializer (vì nó có hiệu suất tốt hơn trên XmlSerilaizer) khi lớp thực thể đến có thể thay đổi không?
  • LINQ có nên thực sự được sử dụng để tuần tự hóa không? Hoặc là nó thực sự tốt cho những thứ khác hơn là truy vấn?
  • XmlSerializer có thể được ưu tiên hơn LINQ trong những trường hợp như vậy không? Nếu đúng thì tại sao?

Trả lời

9

Tôi đồng ý với câu trả lời của @Werner Strydom.

Tôi đã quyết định sử dụng XmlSerializer vì mã trở nên có thể duy trì và nó cung cấp hiệu suất tôi mong đợi. Quan trọng nhất là nó mang lại cho tôi toàn quyền kiểm soát cấu trúc XML.

Đây là cách tôi giải quyết vấn đề của tôi:

Tôi tạo ra các lớp thực thể (đại diện cho nhiều loại hình của các yếu tố Xml) theo yêu cầu của tôi và thông qua một thể hiện của lớp gốc (lớp đại diện cho phần tử gốc) thông qua XmlSerializer .

sử dụng nhỏ LINQ trong trường hợp 1: mối quan hệ M:

Bất cứ nơi nào tôi muốn cùng nguyên tố (nói Employee) nhiều lần dưới nút cụ thể (nói Department), tôi tuyên bố là tài sản của loại List<T>. ví dụ. public List<Employee> Employees trong lớp Department. Trong những trường hợp như vậy, XmlSerializer rõ ràng đã thêm một phần tử có tên là Employees (là nhóm tất cả các phần tử Employee) dưới nút Department. Trong những trường hợp như vậy, tôi đã sử dụng LINQ (sau khi XmlSerializer tuần tự hóa đối tượng .NET) để thao tác XElement (ví dụ: XML) được tạo bởi XmlSerializer. Sử dụng LINQ, tôi chỉ cần đặt tất cả các nút Employee trực tiếp dưới Department nút và đã xóa nút Employees.

Tuy nhiên, tôi nhận được hiệu suất mong đợi bằng cách kết hợp xmlSerializerLINQ.

Nhược điểm là, tất cả các lớp tôi đã tạo phải công khai khi chúng có thể rất nội bộ!

Tại sao không DataContractSerializerLINQ-to-XML?

  • DataContractSerializer không cho phép sử dụng thuộc tính Xml (trừ khi tôi triển khai IXmlSerializable). Xem types supported by DataContractSerializer.
  • LINQ-to-XML (và IXmlSerializable quá) làm cho mã vụng về trong khi tạo cấu trúc XML phức tạp và mã đó chắc chắn sẽ khiến các nhà phát triển khác gãi đầu trong khi duy trì/thay đổi nó.

Còn cách nào khác không?

  • Có. Như đã đề cập bởi @Werner Strydom, bạn có thể tạo các lớp học rất tốt bằng cách sử dụng XSD.exe hoặc công cụ như Xsd2Code và làm việc trực tiếp với chúng nếu bạn hài lòng với các lớp kết quả.
7

Tôi sẽ chọn XmlSerializer vì nó duy trì nhất cho giản đồ tùy chỉnh (giả sử bạn có XSD). Khi bạn đã hoàn thành việc phát triển hệ thống, hãy kiểm tra toàn bộ hiệu suất của nó và xác định xem xê-ri hóa XML có gây ra vấn đề hay không. Nếu có, bạn có thể thay thế nó bằng thứ gì đó đòi hỏi nhiều công việc hơn và kiểm tra lại nó để xem có bất kỳ lợi ích nào không. Nhưng nếu tuần tự hóa XML không phải là một vấn đề, thì bạn có mã duy trì được.

Thời gian cần để phân tích cú pháp một đoạn dữ liệu XML nhỏ có thể không đáng kể so với giao tiếp với cơ sở dữ liệu hoặc hệ thống bên ngoài. Trên các hệ thống có bộ nhớ lớn (16GB +), bạn có thể thấy GC là nút cổ chai trong .NET 4 trở về trước (.NET 4.5 cố gắng giải quyết vấn đề này), đặc biệt khi bạn làm việc với các tập dữ liệu và luồng dữ liệu rất lớn.

Sử dụng AutoMapper để ánh xạ đối tượng được tạo bởi XSD.EXE cho đối tượng của bạn. Điều này sẽ cho phép thiết kế cơ sở dữ liệu thay đổi mà không ảnh hưởng đến dịch vụ web.

Một điều tuyệt vời về LINQ to XML là XSD validation. Tuy nhiên, điều đó ảnh hưởng đến hiệu suất.

1

Một tùy chọn khác là sử dụng LINQ và Reflection để tạo lớp chung để tuần tự hóa đối tượng của bạn thành XML. Một ví dụ điển hình về điều này có thể được tìm thấy tại http://primecoder.blogspot.com/2010/09/how-to-serialize-objects-to-xml-using.html. Tôi không chắc XML của bạn sẽ trông như thế nào vào cuối ngày, nhưng nếu nó khá cơ bản thì điều này có thể làm được điều đó. Bạn sẽ không cần phải thay đổi khi các lớp thực thể của bạn thêm/xóa/thay đổi các thuộc tính, và bạn có thể sử dụng nó trên tất cả các đối tượng của bạn (và các dự án khác nếu được lưu trữ trong một tiện ích DLL).

+0

Cảm ơn bạn đã chia sẻ liên kết. Các giải pháp được cung cấp ở đó không hữu ích cho vấn đề của tôi nhưng nó đã giúp để biết thêm một cách để sử dụng LINQ! – Learner