2012-06-20 31 views
7

Tôi có một chút vấn đề duy nhất. Tôi đang đăng ký một dll như một hội đồng bên trong của một cơ sở dữ liệu SQL Server có một biến SQLXml, cùng với hai chuỗi, và tuần tự hóa dữ liệu thành định dạng JSON.Deserializing XML thành JSON mà không sử dụng hàm XmlDocument.Loadxml()

Để tham khảo, đây là lời gọi phương thức:

[SqlProcedure] 
public static void Receipt(SqlString initiatorPassword, 
          SqlString initiatorId, 
          SqlXml XMLOut, 
          out SqlString strMessge) 

Tôi sẽ sử dụng Newtonsoft.Json hoặc Jayrock cho ứng dụng này nếu điều này là bất kỳ loại khác của ứng dụng. Bình thường, tôi sẽ làm theo câu trả lời cho here và làm điều gì đó tương tự như:

XmlReader r = (XmlReader)XmlOut.CreateReader(); 
XmlDocument doc = new XmlDocument(); 
doc.load(r); 

Tuy nhiên, kể từ khi tôi đang sử dụng SQLCLR, có những quy tắc nhất định của con đường. Một trong số đó là .Load() và không thể sử dụng bất kỳ phương pháp kế thừa nào khác. Tôi nghĩ khuôn khổ .Net cho biết tốt nhất:

System.InvalidOperationException: Không thể tải cụm nối tiếp được tạo động. Trong một số môi trường lưu trữ chức năng tải lắp ráp bị hạn chế, cân nhắc sử dụng bộ nối tiếp được tạo trước. Vui lòng xem ngoại lệ bên trong để biết thêm thông tin. ---> System.IO.FileLoadException:
LoadFrom(), LoadFile(), Load (byte []) và LoadModule() đã bị vô hiệu hóa bởi máy chủ.

Tôi không thông thạo trong SQLCLR bằng bất kỳ phương tiện, nhưng nếu tôi hiểu biết một cách chính xác this blog, điều này được gây ra bởi các quy tắc SQLCLR của không cho phép Load() và kế thừa phương pháp mà không bị ký hợp đồng với và có một tên mạnh. DLL của tôi và DLL của bên thứ ba mà tôi đang sử dụng không có tên mạnh và tôi cũng có thể tự xây dựng lại và ký tên cho họ. Vì vậy, điều này khiến tôi bị mắc kẹt với cố gắng hoàn thành nhiệm vụ này mà không cần sử dụng tải (Trừ khi ai đó biết cách khác có thể thực hiện được)

Giải pháp duy nhất tôi có thể đưa ra là một vòng lặp rất xấu nhưng không hoạt động đúng cách , Tôi đã nhận được một "Jayrock.Json.JsonException: Một giá trị thành viên JSON bên trong một đối tượng JSON phải được đặt trước bởi tên thành viên của nó" ngoại lệ. Đây là vòng lặp trong khi tôi đã viết (không mã tốt nhất của tôi, tôi biết):

int lastdepth = -1; 
Boolean objend = true; 
Boolean wt = false; 
//Write Member/Object statements for the header omitted 
JsonWriter w = new JsonTextWriter() 
while (m.Read()) 
       { 
        if ((lastdepth == -1) && (m.IsStartElement())) 
        {//Checking for root element 
         lastdepth = 0; 
        } 
        if ((m.IsStartElement()) && (lastdepth != -1)) 
        {//Checking for Start element (<html>) 
         w.WriteMember(m.Name); 
         if (objend) 
         { //Check if element is new Parent Node, if so, write start object 
          w.WriteStartObject(); 
          objend = false; 
         } 
        } 
        if (m.NodeType == XmlNodeType.Text) 
        { //Writes text here. NOTE: m.Depth > lastdepth here!!!!!!! 
         w.WriteString(m.Value); 
         wt = true; 
        } 
        if (m.NodeType == XmlNodeType.Whitespace) //If whitespace, keep on truckin 
        { m.Skip(); } 
        if ((m.NodeType == XmlNodeType.EndElement) && (wt == false) && (lastdepth > m.Depth)) 
        {//End element that ends a series of "Child" nodes 
         w.WriteEndObject(); 
         objend = true; 
        } 
        if ((m.NodeType == XmlNodeType.EndElement) && (wt == true))//Standard end of an el 
        { wt = false; } 
        lastdepth = m.Depth; 
       } 
       w.WriteEndObject(); 
       jout = w.ToString(); 
} 

Câu hỏi của tôi là, vì tôi không thể sử dụng .load() và vòng lặp trong khi tôi là một mớ hỗn độn để gỡ lỗi, những gì sẽ là tốt nhất cách tiếp cận ở đây? Cách tiếp cận khác thường được thảo luận là deserialization vào một đối tượng với các biến phù hợp nhưng tôi có một XML khá lớn sắp ra khỏi SQL Server. Vòng lặp của tôi là một nỗ lực trong lập trình động vì có ~ 200 trường đang được kéo để tạo XML này.

Lưu ý: Tôi đang sử dụng Jayrock và làm việc trong .Net Framework 2.0. Tôi không thể thay đổi phiên bản khung tại thời điểm này.

+0

AFAIK 'XmlDocument.LoadXml()' không cần dẫn đầu các cụm động. Bạn có chắc là bạn không cố gắng sử dụng xê-ri hóa XML thay thế không? Bạn có thể đăng theo dõi ngăn xếp của ngoại lệ không? – svick

Trả lời

0

Code For JayRock

Mã của bạn là ném một ngoại lệ:

A JSON member value inside a JSON object must be preceded by its member name. 

ngoại lệ này xuất phát từ phương pháp:

private void EnsureMemberOnObjectBracket() 
    { 
     if (_state.Bracket == JsonWriterBracket.Object) 
      throw new JsonException("A JSON member value inside a JSON 
      object must be preceded by its member name."); 
    } 

Cuộc gọi có chứa từ mã đó là từ:

public sealed override void WriteString(string value) 
    { 
     if (Depth == 0) 
     { 
      WriteStartArray(); WriteString(value); WriteEndArray(); 
     } 
     else 
     { 
      EnsureMemberOnObjectBracket(); 
      WriteStringImpl(value); 
      OnValueWritten(); 
     } 
    } 

Thời gian duy nhất mà mã của bạn gọi một phương pháp trong đó kêu gọi EnsureMemberOnObjectBracket là từ một nơi:

if (m.NodeType == XmlNodeType.Text) 
{ //Writes text here. NOTE: m.Depth > lastdepth here!!!!!!! 
w.WriteString(m.Value); 
wt = true; 
} 

Điều này có nghĩa rằng có một lỗi ở đây. Có lẽ bạn có thể làm một số thử/bắt, hoặc tinh chỉnh mã của bạn ở đây.

1

Tôi hy vọng điều này có thể áp dụng cho bạn, nhưng sẽ không biết trừ khi bạn thử. Từ here:

EXTERNAL_ACCESS giải quyết các tình huống trong đó các mã cần truy cập nguồn lực bên ngoài máy chủ, chẳng hạn như các file, mạng, registry, và biến môi trường. Bất cứ khi nào máy chủ truy cập tài nguyên bên ngoài , nó sẽ mạo danh bối cảnh bảo mật của người dùng gọi là mã được quản lý .

Sự cho phép mã UNSAFE dành cho những trường hợp trong đó hội đồng là không an toàn hoặc yêu cầu quyền truy cập bổ sung vào các tài nguyên bị hạn chế , chẳng hạn như Microsoft Win32 API.

Tôi tin rằng một trong hai điều này là những gì bạn cần, có thể là EXTERNAL_ACCESS. Thêm:

Chúng tôi khuyên bạn nên tạo khóa không đối xứng từ tệp lắp ráp trong cơ sở dữ liệu chính. Đăng nhập được ánh xạ tới khóa bất đối xứng này phải sau đó được tạo và thông tin đăng nhập phải được cấp quyền truy cập EXTERNAL ACCESS ASSEMBLY hoặc UNSAFE ASSEMBLY.

Lưu ý: Bạn phải tạo thông tin đăng nhập mới để liên kết với khóa không đối xứng. Đăng nhập này chỉ được sử dụng để cấp quyền; nó không phải là được liên kết với người dùng hoặc được sử dụng trong ứng dụng.

Và mã có liên quan (Tôi đã sử dụng này thành công trong quá khứ):

USE master; 
GO 

CREATE ASYMMETRIC KEY SQLCLRTestKey FROM EXECUTABLE FILE = 'C:\MyDBApp\SQLCLRTest.dll' 
CREATE LOGIN SQLCLRTestLogin FROM ASYMMETRIC KEY SQLCLRTestKey 
GRANT EXTERNAL ACCESS ASSEMBLY TO SQLCLRTestLogin; 
GO 

Tôi tưởng tượng bạn cũng muốn Tạo serialization lắp ráp bật trong dự án của bạn.

Điều này tránh được câu hỏi của bạn trong thực tế, nhưng đây thực sự là cách ưu tiên để cho phép các DLL khác được tải thành công để bạn có thể viết mã chính xác.

+0

AH! Tôi ước gì tôi đã thấy điều này trước khi tôi thay đổi toàn bộ chương trình của tôi vì lỗi này. Cảm ơn bạn rất nhiều, tôi chắc chắn tôi sẽ phải sử dụng điều này sớm! – ScruffMcGruff

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