Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将.net DateTime的Dapper映射更改为使用DbType DateTime2,然后再次将其恢复_C#_Sql Server_Datetime_Dapper_Datetime2 - Fatal编程技术网

C# 将.net DateTime的Dapper映射更改为使用DbType DateTime2,然后再次将其恢复

C# 将.net DateTime的Dapper映射更改为使用DbType DateTime2,然后再次将其恢复,c#,sql-server,datetime,dapper,datetime2,C#,Sql Server,Datetime,Dapper,Datetime2,与问题相似;但我希望以后能把它放回去 对于这个问题,目前公认的答案是更改一个简洁的源文件;但是我使用的是NuGet软件包,所以这对我来说不起作用。正如对公认答案的第一条评论所指出的,这是不可逆的——“如果一些是DateTime,而另一些是DateTime2呢?”——这就是我的场景:不同的查询需要不同的映射(每个查询只需要一个或另一个) 我在用这个词来回答同样的问题。然而,这种方法似乎也是不可逆的。似乎在第一次查询完成时设置的任何值都将保持不变,并且在之后都不会更改 以下代码是一个MCVE。如果运

与问题相似;但我希望以后能把它放回去

对于这个问题,目前公认的答案是更改一个简洁的源文件;但是我使用的是NuGet软件包,所以这对我来说不起作用。正如对公认答案的第一条评论所指出的,这是不可逆的——“如果一些是DateTime,而另一些是DateTime2呢?”——这就是我的场景:不同的查询需要不同的映射(每个查询只需要一个或另一个)

我在用这个词来回答同样的问题。然而,这种方法似乎也是不可逆的。似乎在第一次查询完成时设置的任何值都将保持不变,并且在之后都不会更改

以下代码是一个MCVE。如果运行它,您将看到类型始终显示为“datetime”,并且值的精度永远不会超过毫秒(正如您对datetime所期望的那样);尽管有人试图更改映射。然后您必须注释掉对“PerformDapperQuery()”的第一个调用,然后再次运行它:现在您将看到该类型始终返回为“datetime2”,并且这些值的精度为7位数,精确到一秒的小数点(正如您对datetime2所期望的那样)

因此,问题的第一部分是:如何多次更改Dapper的DateTime映射?问题的第二部分是我想恢复以前的映射;但正如您所看到的,
LookupDbType
被标记为过时,所以我对是否有其他方法感兴趣

在不信者Damien_给出缓存解释后进行编辑

我将上面的查询更改为$“SELECT sql_variant_property(@Param,'BaseType'),CAST(@Param AS datetime2(7))--{DateTime.Now:o}”,这样每次都会有所不同,这确实改变了行为

我遇到这个问题的原因是,我想添加一些东西来包装特定的简洁查询,使它们使用
DateTime2
而不是
DateTime
,因此我编写了这个类:

internal sealed class DapperDateTime2MapperScope : IDisposable
{
    private readonly DbType? _predecessor;
    private bool _isDisposed;

    public DapperDateTime2MapperScope()
    {
        _predecessor = SqlMapperGetDbType();
        SqlMapper.AddTypeMap(typeof(DateTime), DbType.DateTime2);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!_isDisposed)
        {
            if (disposing)
            {
                if (_predecessor.HasValue)
                {
                    SqlMapper.AddTypeMap(typeof(DateTime), _predecessor.Value);
                }
            }

            _isDisposed = true;
        }
    }

    private DbType SqlMapperGetDbType()
    {
#pragma warning disable 618
        return SqlMapper.LookupDbType(typeof(DateTime), null, false, out var handler);
#pragma warning restore 618
    }
}
然后,可以使用它将Dapper查询包装到using块中,以使该查询使用DateTime2映射:

using (new DapperDateTime2MapperScope())
{
    -- Perform Dapper query here
}

然后我编写了该类的单元测试——一个测试没有使用
,另一个测试使用
;我发现单元测试相互作用:它们可以单独工作,但当所有测试都运行时,一个或另一个测试会失败。原因(多亏了Damien的解释)是Dapper对查询的缓存。好消息是,我认为这很好——单元测试遇到了问题,因为它们使用相同的查询;但在我真正的代码库中,如果我使用
将一个特定查询包装在这个
中,那么我总是希望该查询使用该映射。因此,基本上这只是我的单元测试的一个问题,而不是类的真正用法。

您的代码确实正确地更改了类型映射,但dapper积极地缓存查询

如果您的实际查询在
datetime
datetime2
用例之间发生变化(我希望它们会发生变化),那么应该可以。否则,您可以自己清除查询缓存(但显然,这可能会产生其他不希望的后果):


对于使用
LookupDbType
,我认为您可以使用
GetDbType

GetDbType也过时了;但是缓存确实是一个问题,所以我将把它标记为答案并编辑这个问题,以解释在我为检查行为而编写的单元测试中这是如何发生的,以及(现在我已经考虑过了)为什么在实际代码中它实际上不是一个问题。谢谢
using (new DapperDateTime2MapperScope())
{
    -- Perform Dapper query here
}
        public static void Main()
        {
            // I know this is marked as obsolete, and I am open to suggestions for alternatives.
            // see https://github.com/StackExchange/Dapper/issues/798
#pragma warning disable 618
            var oldValue = SqlMapper.LookupDbType(typeof(DateTime), null, false, out var handler);
#pragma warning restore 618

            PerformDapperQuery();
            SqlMapper.AddTypeMap(typeof(DateTime), DbType.DateTime2);
            SqlMapper.PurgeQueryCache();
            PerformDapperQuery();
            SqlMapper.AddTypeMap(typeof(DateTime), DbType.DateTime);
            SqlMapper.PurgeQueryCache();
            PerformDapperQuery();
            SqlMapper.AddTypeMap(typeof(DateTime), oldValue);
            SqlMapper.PurgeQueryCache();
            PerformDapperQuery();
        }