使用 TableValuedParameter 和 Dapper 将字符串转换为 smalldatetime 失败

Posted

技术标签:

【中文标题】使用 TableValuedParameter 和 Dapper 将字符串转换为 smalldatetime 失败【英文标题】:Using TableValuedParameter with Dapper Conversion Fails for string to smalldatetime 【发布时间】:2020-04-21 07:43:21 【问题描述】:

使用 dapper 将数据表转换为 TableValuedParameter 时出现此错误。我在转换为数据表时遗漏了什么,DBNull.Value 是否适用于可为空的日期时间?是否存在我在代码中没有看到的映射错误的属性?

System.Private.CoreLib:执行函数时出现异常:MyProject。 Core .Net SqlClient 数据提供程序:将字符串转换为 smalldatetime 数据类型时转换失败。

我在数据表中创建数据列表

List<PersonData> personDatas = maps.Select( mappedData =>
    new PersonData
    
        PersonId = mappedData.PersonId,
        StartDate = mappedData.StartDate,
        EndDate = mappedData.EndDate,
        CurrentDate = DateTime.Now,
        SomeString = mapped.SomeStringData
    )
    .ToList()
    .ToDataTable();

Method for ToDataTable can be found here

PersonData 定义为

public class PersonData

    public int PersonId  get; set; 
    public DateTime? StartDate  get; set; 
    public DateTime? EndDate  get; set; 
    public string SomeString  get; set;     
    public DateTime? CurrentDate  get; set; 

然后我像这样用 Dapper 执行查询

using (var cn = new SqlConnection(connectionString))

    cn.Open();
    //This is where the exception happens
    cn.Execute(RepositorySql.MergeSql(), new
    
        UserDefinedTable = dataTable.AsTableValuedParameter("[dbo].[PersonData]")       
    );
    cn.Close();

Sql 是

MERGE dbo.tblPersonData AS target
USING @UserDefinedTable AS source
ON target.PersonID = source.PersonID
    WHEN MATCHED
    THEN UPDATE SET 
                    StartDate = source.StartDate, 
                    EndDate = source.EndDate,
                    --UpdatedDate instead of InsertedDate
                    UpdatedDate = source.CurrentDate,
                    SomeString = source.SomeString
    WHEN NOT MATCHED BY TARGET
    THEN
        --Inserted date instead of UpdatedDate
        INSERT(PersonID, StartDate, EndDate, InsertedDate, SomeString)
        VALUES
            (source.PersonId, source.StartDate, source.EndDate, source.CurrentDate, source.SomeString)

用户定义表是

CREATE TYPE [dbo].[PersonData] AS TABLE(    
   PersonId int NOT NULL
   ,SomeString varchar(50) null
   ,StartDate smalldatetime null
   ,EndDate smalldatetime null
   ,CurrentDate smalldatetime null)

【问题讨论】:

【参考方案1】:

问题是因为对象的序列化将列的顺序与用户定义表的顺序不同,因此他们试图将日期保存到字符串列中。我将对象更改为 this 并解决了错误,请注意属性的顺序已更改:

public class PersonData

    public int PersonId  get; set; 
    public string SomeString  get; set;  
    public DateTime? StartDate  get; set; 
    public DateTime? EndDate  get; set;    
    public DateTime? CurrentDate  get; set; 

【讨论】:

以上是关于使用 TableValuedParameter 和 Dapper 将字符串转换为 smalldatetime 失败的主要内容,如果未能解决你的问题,请参考以下文章

使用java加密和解密密码使用啥API和算法

如何使用 php 和 mysql 使用纬度和经度进行几何搜索

Cocoa - 为啥使用 NSInteger 和 CGFloat 而不是使用 int 和 float,或者总是使用 NSNumber?

HTTPS和SSH方式的区别和使用

学习和使用SVN和GitHub——开篇

CPU使用率和正在使用的内存之间有啥关系?