SQL DateTime2类型

时间:2017-12-22 22:04:12

标签: c# .net datetime

尝试导入SqlDataRecord数据类型的DateTime2时,我遇到抛出的异常。此代码段中没有抛出任何异常,但后面的异常的原因在以下代码中很明显。

using System;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data;
using System.Web.UI.WebControls;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Diagnostics;

namespace Testing123
{
    public class Program
    {
        public static object SQLTParser(SqlMetaData smd, string val)
        {
            TypeCode systc = Parameter.ConvertDbTypeToTypeCode(smd.DbType);

            try
            {
                return Convert.ChangeType(val, systc);
            }
            catch (Exception ex)
            {
                if (ex is InvalidCastException || ex is FormatException || ex is OverflowException)
                {
                    Console.WriteLine("Exception reached casting " + val + " to " + Type.GetType("System." + Enum.GetName(typeof(TypeCode), systc)) + ": " + ex.Message + ex.ToString()); //smd.GetType().Name 
                    return null;
                }
                else
                {
                    Console.WriteLine("Null value exception");
                    return null;
                }
            }
        }

        public static void Main()
        {
            SqlMetaData sqmd = new SqlMetaData("dt", SqlDbType.DateTime2, 27, 7);
            SqlDataRecord sdr = new SqlDataRecord(sqmd);
            sdr.SetValue(0, SQLTParser(sqmd, "2017-01-12 01:23:12.3456789"));
            //set BreakPoint
            //sdr -> Non-Public members -> _columnMetaData[0] -> Precision = 27
            //sdr -> Non-Public members -> _columnSmiMetaData[0] -> Non-Public members -> Precision = 0
        }
    }
}

如上所述,如果您设置断点并按照MS Visual Studio *中的指示进行监视,则精确度不会匹配columnMetaData和columnSmiMetaData,而第二个此类条目(!!)会抛出异常:

  

记录“2”的字段“dt”的元数据与原始记录的元数据不匹配。

匹配

引发的异常

line 3755 of ValueUtilsSmi

由于MetadataUtilsSmi.IsCompatible

的归还

本质上,记录2的字段元数据中的精度与记录1的SmiMetaData中的精度不匹配。在记录1中,MD和SMD也不匹配,但基于逻辑Microsoft正在使用IEnumerator'd SqlDataRecord,它在第2条记录之前不会成为问题。

这是MS的错误吗?或者有办法强制SmiMetaData的精度值?或者忽略ValueUtilsSmi中的特定字段检查?指定SqlMetaData sqmd = new SqlMetaData("dt", SqlDbType.DateTime2, 0, 7);允许解析继续进行,但从数据中删除亚秒精度。

简而言之,我是如何尝试将数据发送到数据库的。如果这部分不是一个完整的例子,请道歉。

public class FullStreamingDataRecord : IEnumerable<SqlDataRecord>
{
    private string _filePath;
    public bool _hasHeader { get; private set; }
    private ParserDict _pd; //notably has colStructure which is an array of SqlMetaData[]

    public FullStreamingDataRecord(string FilePath, ParserDict pd)
    {
        _filePath = FilePath;
        _pd = pd;
        _hasHeader = true;
    }

    public static object SQLTParser(SqlMetaData smd, string val)
    {
        TypeCode systc = Parameter.ConvertDbTypeToTypeCode(smd.DbType);

        try
        {
            return Convert.ChangeType(val, systc);
        }
        catch (Exception ex)
        {
            if (ex is InvalidCastException || ex is FormatException || ex is OverflowException)
            {
                Console.WriteLine("Exception reached casting " + val + " to " + Type.GetType("System."+Enum.GetName(typeof(TypeCode),systc)) + ": " + ex.Message + ex.ToString()); //smd.GetType().Name 
                return null; //smd.TParse(val);
            }
            else
            {
                Console.WriteLine("Null value exception casting...attempting a different method");
                return null; smd.TParse(val);
            }
        }
    }

    public IEnumerator<SqlDataRecord> GetEnumerator()
    {
        int len = this._pd.colStructure.Length;
        StreamReader fileReader = null;

        try
        {
            using (fileReader = new StreamReader(this._filePath))
            {
                string inputRow = "";
                string[] inputColumns = new string[len];

                if (_hasHeader && !fileReader.EndOfStream)
                {
                    inputRow = fileReader.ReadLine(); //and ignore
                }

                while (!fileReader.EndOfStream)
                { 
                    string temp = "";
                    inputRow = fileReader.ReadLine();
                    inputColumns = inputRow.Split(new char[]{','},len);
                    SqlDataRecord dataRecord = this._pd.colStructure

                    for (int j = 0; j < len; j++) { // i = counter for input columns
                        string currentKey = this._pd.colStructure[j].SqlMetaData.Name;
                        string curval = inputColumns[j];
                        var ty = this._pd.colStructure[j].SqlMetaData; //.DbType;
                        dataRecord.SetValue(j, SQLTParser(ty, curval));
                        // dataRecord.GetSqlMetaData(j).Adjust(dataRecord.GetValue(j));
                    }

                    yield return dataRecord;
                }
            }
        }
        // no catch block allowed due to the "yield" command
        finally 
        {
            fileReader.Close();
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

我在我的Main()

中调用它
using (SqlConnection conn = new DBConnect().conn)
{
    conn.Open();

    SqlCommand importProc = new SqlCommand("tvp_"+pd.tableDestination, conn);
    importProc.CommandType = CommandType.StoredProcedure;
    importProc.CommandTimeout = 300;

    SqlParameter importTable = new SqlParameter();
    importTable.ParameterName = "@ImportTable";
    importTable.TypeName = "dbo.tt_"+pd.tableDestination;
    importTable.SqlDbType = SqlDbType.Structured;
    importTable.Value = new FullStreamingDataRecord(fn, pd);
    importProc.Parameters.Add(importTable);

    importProc.ExecuteNonQuery(); //this line throws the exception
}

抱歉不Console.WriteLine这些手表的价值。

不幸的是,似乎使用Reflection的sdr.GetType()。GetProperties()来保护这些参数不受检查,即使设置了适当的BindingFlags也是如此。但至少你可以在调试模式下看到这些值!

0 个答案:

没有答案