在CoreFx上使用System.Data.SqlClient时出现UDT不支持的令牌问题

时间:2016-06-22 01:51:27

标签: c# .net sql-server .net-core

我创建了一个基本的.Net Core Console测试应用程序,用于连接本地Sql Server实例并检索数据。在定位.Net 4.6.1时,相同的代码可以正常工作,但在定位.Net Core时则不行。

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Dynamic;
using System.Linq;
using System.Text;

namespace SqlServerTests
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                StringBuilder statement = new StringBuilder("SELECT * FROM calendars as i WHERE i.Id='[id]");

                SqlConnection sqlConnection = new SqlConnection("[Connection works fine]");

                sqlConnection.Open();

                SqlCommand sqlCommand = new SqlCommand(statement.ToString(), sqlConnection);
                SqlDataReader sqlReader = sqlCommand.ExecuteReader();

                if (!sqlReader.HasRows)
                    Console.WriteLine("No data found"); ;

                List<dynamic> dataSet = new List<dynamic>();

                if (sqlReader.HasRows)
                    while (sqlReader.Read())
                    {
                        dynamic dataObject = new ExpandoObject();
                        var data = dataObject as IDictionary<string, object>;

                        for (int i = 0; i < sqlReader.FieldCount; i++)
                            data[sqlReader.GetName(i)] = !sqlReader.IsDBNull(i) ? sqlReader.GetValue(i) : null;

                        dataSet.Add(data);
                    }

                Console.WriteLine(dataSet.FirstOrDefault());

                sqlConnection.Close();
            }
            catch(Exception exception)
            {
                //Exception code omitted
            }
        }
    }
}

连接工作(另一个应用程序使用相同的连接来保存数据),并且在运行Sql Server Profiler时,查询按预期执行(在将查询粘贴到Sql Server Management Studio时也会按预期检索数据),但是在调用时控制台应用程序上的ExecuteReader我收到以下消息:

  

服务器正在尝试使用非功能   在这个平台上支持。收到了一个不受支持的令牌'Udt'而   从服务器读取数据。   在System.Data.SqlClient.TdsParser.TryCommonProcessMetaData(TdsParserStateObject)   stateObj,_SqlMetaData col)at   System.Data.SqlClient.TdsParser.TryProcessMetaData(Int32 cColumns,   TdsParserStateObject stateObj,_SqlMetaDataSet&amp; metaData)at   System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,   SqlCommand cmdHandler,SqlDataReader dataStream,   BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject   stateObj,布尔&amp; dataReady)at   System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()at   System.Data.SqlClient.SqlDataReader.get_MetaData()at   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,   RunBehavior runBehavior,String resetOptionsString)at   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean   async,Int32超时,任务&amp; task,Boolean asyncWrite,SqlDataReader   ds)at   System.Data.SqlClient.SqlCommand.ExecuteReader(的CommandBehavior   行为,String方法)at   System.Data.SqlClient.SqlCommand.ExecuteReader()at   SqlServerTests.Program.Main(String [] args)in ...

我假设我在.Net Core应用程序中使用此代码时遗漏了一些内容,但我找不到。

1 个答案:

答案 0 :(得分:1)

查看SqlClient源代码,看起来UDT仍然非常不受支持。在我的情况下,我试图插入包含HierarchyId列的记录。我收到&#39;服务器正在尝试使用此平台不支持的功能。&#39;来自TdsParser。

班级(目前)在这里: https://github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs

如果您搜索SQLUDT,您将找到类似于以下内容的条目:

case TdsEnums.SQLUDT:
    throw SQL.UnsupportedFeatureAndToken(_connHandler, SqlDbType.Udt.ToString());

这是MyGet Package:System.Data.SqlClient 4.1.1-beta-24222-02

更新:我能够通过在字符串表示中发送HierarchyId来获得一个简单的插入语句来通过Dapper工作。在这个阶段,SqlBulkCopy仍然是一个禁忌。从读取的角度来看,如果我在SELECT语句中引用HierarchyId列,则会收到不受支持的异常。但是,在SQL查询中使用SQL转换CONVERT(varchar(8000), [HierarchyColumn])至少会成功返回字符串表示。

这是有道理的,它不像我们可以访问现有的UDT类,如SqlHierarchyId。

如果您更改原始StringBuilder statement = new StringBuilder("SELECT * FROM calendars as i WHERE i.Id='[id]");以便SELECT语句显式引用列并在UDT列上执行转换,那么您应该获得更有用的内容。