.net core ExecuteXmlReader在从SQL Server获取特定JSON时失败
我有一个现有的工作流程,它使用.net core ExecuteXmlReader在从SQL Server获取特定JSON时失败,.net-core,asp.net-core-2.0,sqlcommand,.net Core,Asp.net Core 2.0,Sqlcommand,我有一个现有的工作流程,它使用for JSON指令从SQL Server中的存储过程接收生成的JSON。但是当在列数据中接收到特定文本时,ExecuteXmlReader在Read操作中出现故障 例外情况 XmlException:“=”是意外标记。所需的标记为“;”。 第1行,位置94 如果我控制输出,我很可能会把它放在CDATA区域 从SQL Server返回的数据 JSON_F52E2B61-18A1-11d1-B105-00805F49916B {"photoId":1000000007
for JSON
指令从SQL Server中的存储过程接收生成的JSON。但是当在列数据中接收到特定文本时,ExecuteXmlReader
在Read
操作中出现故障
例外情况
XmlException:“=”是意外标记。所需的标记为“;”。
第1行,位置94
如果我控制输出,我很可能会把它放在CDATA区域
从SQL Server返回的数据
JSON_F52E2B61-18A1-11d1-B105-00805F49916B
{"photoId":1000000007,"photoType":"image\/gif","photoUrl":"https:\/\/slack-imgs.com\/?c=1&url=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F3o84U9arAYRM73AIvu%2Fgiphy-downsized.gif" }
最终JSON字符串,该字符串应通过Read
{
"photoId": 1000000007,
"photoType": "image/gif",
"photoUrl": "https://slack-imgs.com/?c=1&url=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F3o84U9arAYRM73AIvu%2Fgiphy-downsized.gif",
"isActive": true
}
保存到表中的URL
https://slack-imgs.com/?c=1&url=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F3o84U9arAYRM73AIvu%2Fgiphy-downsized.gif
public static SqlJSONReader ExecuteJsonReader(this SqlCommand cmd)
{
var rdr = cmd.ExecuteReader();
return new SqlJSONReader(rdr);
}
public class SqlJSONReader : System.IO.TextReader
{
private SqlDataReader SqlReader { get; set; }
private string CurrentLine { get; set; }
private int CurrentPostion { get; set; }
public SqlJSONReader(SqlDataReader rdr)
{
CurrentLine = "";
CurrentPostion = 0;
this.SqlReader = rdr;
}
public override int Peek()
{
return GetChar(false);
}
public override int Read()
{
return GetChar(true);
}
public int GetChar(bool Advance)
{
while (CurrentLine.Length == CurrentPostion)
{
if (!SqlReader.Read())
{
return -1;
}
CurrentLine = SqlReader.GetString(0);
CurrentPostion = 0;
}
var rv = CurrentLine[CurrentPostion];
if (Advance)
CurrentPostion += 1;
return rv;
}
public string ReadAll()
{
var sbResult = new StringBuilder();
if (SqlReader.HasRows)
{
while (SqlReader.Read())
sbResult.Append(SqlReader.GetString(0));
}
else
return string.Empty;
// Clean up any JSON escapes before returning
return JsonConvert.DeserializeObject(sbResult.ToString()).ToString();
}
public override void Close() { SqlReader.Close(); }
}
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "exec [dbo].[GetPhoto] @PhotoId=4";
conn.Open();
var rdr = cmd.ExecuteJsonReader();
string jsonResult = rdr.ReadAll();
conn.Close();
}
最终,这是一个SQL Server 2016更改,但我需要比Microsoft提供的更快的修复。那么,有没有办法通过SQL或C#.Net代码来处理这个问题 奇怪的是,在SSMS中单击表列值JSON时,也会出现同样的错误
我继续建议您使用错误的API来读取JSON查询结果。下面是一个实现SqlCommand.ExecuteJsonReader()扩展方法的小助手类
static class SqlJsonUtils
{
public static Newtonsoft.Json.JsonReader ExecuteJsonReader(this SqlCommand cmd)
{
var rdr = cmd.ExecuteReader();
var jr = new Newtonsoft.Json.JsonTextReader(new SqlJSONReader(rdr));
return jr;
}
class SqlJSONReader : System.IO.TextReader
{
SqlDataReader rdr;
string currentLine = "";
int currentPos = 0;
public SqlJSONReader(SqlDataReader rdr)
{
this.rdr = rdr;
}
public override int Peek()
{
return GetChar(false);
}
public override int Read()
{
return GetChar(true);
}
public int GetChar(bool Advance)
{
while (currentLine.Length == currentPos)
{
if (!rdr.Read())
{
return -1;
}
currentLine = rdr.GetString(0);
currentPos = 0;
}
int rv = (int)currentLine[currentPos];
if (Advance) currentPos += 1;
return rv;
}
public override void Close()
{
rdr.Close();
}
}
}
从那以后,我已经制作了一个可下载的NUGET软件包。有关异步的更新,请参见
我接受了大卫的建议,并将他的答案标记为答案,但我需要整个原始JSON 因此,我添加并删除了对
Newtonsoft.Json.JsonTextReader
的调用,因为它不会只返回字符串,并修改了David的扩展类,通过调用ReadAll
返回整个Json
请注意,它使用Newtonsoft的JsonConvert.DeserializeObject
代码
https://slack-imgs.com/?c=1&url=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F3o84U9arAYRM73AIvu%2Fgiphy-downsized.gif
public static SqlJSONReader ExecuteJsonReader(this SqlCommand cmd)
{
var rdr = cmd.ExecuteReader();
return new SqlJSONReader(rdr);
}
public class SqlJSONReader : System.IO.TextReader
{
private SqlDataReader SqlReader { get; set; }
private string CurrentLine { get; set; }
private int CurrentPostion { get; set; }
public SqlJSONReader(SqlDataReader rdr)
{
CurrentLine = "";
CurrentPostion = 0;
this.SqlReader = rdr;
}
public override int Peek()
{
return GetChar(false);
}
public override int Read()
{
return GetChar(true);
}
public int GetChar(bool Advance)
{
while (CurrentLine.Length == CurrentPostion)
{
if (!SqlReader.Read())
{
return -1;
}
CurrentLine = SqlReader.GetString(0);
CurrentPostion = 0;
}
var rv = CurrentLine[CurrentPostion];
if (Advance)
CurrentPostion += 1;
return rv;
}
public string ReadAll()
{
var sbResult = new StringBuilder();
if (SqlReader.HasRows)
{
while (SqlReader.Read())
sbResult.Append(SqlReader.GetString(0));
}
else
return string.Empty;
// Clean up any JSON escapes before returning
return JsonConvert.DeserializeObject(sbResult.ToString()).ToString();
}
public override void Close() { SqlReader.Close(); }
}
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "exec [dbo].[GetPhoto] @PhotoId=4";
conn.Open();
var rdr = cmd.ExecuteJsonReader();
string jsonResult = rdr.ReadAll();
conn.Close();
}
用法
https://slack-imgs.com/?c=1&url=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2F3o84U9arAYRM73AIvu%2Fgiphy-downsized.gif
public static SqlJSONReader ExecuteJsonReader(this SqlCommand cmd)
{
var rdr = cmd.ExecuteReader();
return new SqlJSONReader(rdr);
}
public class SqlJSONReader : System.IO.TextReader
{
private SqlDataReader SqlReader { get; set; }
private string CurrentLine { get; set; }
private int CurrentPostion { get; set; }
public SqlJSONReader(SqlDataReader rdr)
{
CurrentLine = "";
CurrentPostion = 0;
this.SqlReader = rdr;
}
public override int Peek()
{
return GetChar(false);
}
public override int Read()
{
return GetChar(true);
}
public int GetChar(bool Advance)
{
while (CurrentLine.Length == CurrentPostion)
{
if (!SqlReader.Read())
{
return -1;
}
CurrentLine = SqlReader.GetString(0);
CurrentPostion = 0;
}
var rv = CurrentLine[CurrentPostion];
if (Advance)
CurrentPostion += 1;
return rv;
}
public string ReadAll()
{
var sbResult = new StringBuilder();
if (SqlReader.HasRows)
{
while (SqlReader.Read())
sbResult.Append(SqlReader.GetString(0));
}
else
return string.Empty;
// Clean up any JSON escapes before returning
return JsonConvert.DeserializeObject(sbResult.ToString()).ToString();
}
public override void Close() { SqlReader.Close(); }
}
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "exec [dbo].[GetPhoto] @PhotoId=4";
conn.Open();
var rdr = cmd.ExecuteJsonReader();
string jsonResult = rdr.ReadAll();
conn.Close();
}
你能澄清你的客户代码吗?我对ExecuteXmlReader()的角色感到困惑,因为JSON查询通常是使用ExecuteReader()读取的。这能解决2033个字符的分页问题吗?按照Microsoft的说法,“如果您使用ExecuteReader或BeginExecuteReader访问XML数据,SQL Server将返回长度大于2033个字符的XML结果,每行包含2033个字符。要避免这种行为,请使用ExecuteXmlReader或BeginExecuteXmlReader读取XML查询。有关更多信息,请参阅文章Q310378。”PRB:当您使用SqlDataReader时,XML数据会被截断,“位于Microsoft知识库中。”是的!GetChar(bool)将根据需要推进DataReader。这就是我最初写这段代码的原因。谢谢你的代码。我将你的答案标记为答案,因为它为我提供了正确阅读行流(esque)所需的信息。(感觉我在做.NET1…但我跑题了)。我已经发布了我的最终代码,供任何了解这一点的人使用。谢谢