C# Dapper 和 FastMember - 不支持指定的方法

Posted

技术标签:

【中文标题】C# Dapper 和 FastMember - 不支持指定的方法【英文标题】:C# Dapper and FastMember - Specified method not supported 【发布时间】:2018-01-31 16:14:18 【问题描述】:

我有一个 C# .NET Core 2.0 Web API 项目(作为微服务实现)。

我在我的存储库层中使用 NuGet 包“Dapper”和“FastMember”(最新版本)尝试通过 FastMember 提供的 ObjectReader 将 IEnumerable<T> 转换为 DataTable,以便我可以利用 Dapper 的内置-in ICustomQueryParameter SqlMapper 将表值参数传递给我在 SQL Server 中使用的存储过程。

当我执行和调试我的代码时,它会在 FastMember ObjectReader 尝试加载到 DataTable 的行上引发异常:table.Load(reader);

这是我的 Dapper 包装器/扩展方法,其中包含有问题的行:

public static class DapperExtensions

    public static SqlMapper.ICustomQueryParameter AsTvp<T>(this 
    IEnumerable<T> enumerable, string typeName) where T : class
        
            var table = new DataTable();
            var members = typeof(T).GetProperties().Select(p => p.Name).ToArray();
            using (var reader = ObjectReader.Create(enumerable.ToList(), members))
            
                table.Load(reader);
            
            return table.AsTableValuedParameter(typeName);
        

这是我使用上述扩展方法的 Dapper 调用:

using (var dbConnection = new SqlConnection(_connectionString))

    var result = dbConnection.Query("[PurchaseOrders].[Add] @t***ewPurchaseOrderItems, @StartDate", new
    
        t***ewPurchaseOrderItems = purchaseOrderCreationRequest.PurchaseOrderItems.AsTvp("NewPurchaseOrderType"),
    StartDate = purchaseOrderCreationRequest.StartDate
    );

这是我抛出的 C# 异常的堆栈跟踪:

at System.Data.Common.DbDataReader.GetSchemaTable()
at System.Data.ProviderBase.SchemaMapping..ctor(DataAdapter adapter, DataSet dataset, DataTable datatable, DataReaderContainer dataReader, Boolean keyInfo, SchemaType schemaType, String sourceTableName, Boolean gettingData, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.FillMappingInternal(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.FillMapping(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 schemaCount, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.Fill(DataTable[] dataTables, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
at System.Data.DataTable.Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler)
at System.Data.DataTable.Load(IDataReader reader)
at PurchaseOrderCreationRepositories.Extensions.DapperExtensions.AsTvp[T](IEnumerable`1 enumerable, String typeName) in C:\Projects-Git\Enterprise\PurchaseOrderCreationService\PurchaseOrderCreationRepositories\Extensions\DapperExtensions.cs:line 16
at PurchaseOrderCreationRepositories.PurchaseOrderRepository.Add(IPurchaseOrderCreationRequest purchaseOrderCreationRequest) in C:\Projects-Git\Enterprise\PurchaseOrderCreationService\PurchaseOrderCreationRepositories\PurchaseOrderRepository.cs:line 22
at PurchaseOrderCreationServices.PurchaseOrderService.Add(IPurchaseOrderCreationRequest purchaseOrderCreationRequest) in C:\Projects-Git\Enterprise\PurchaseOrderCreationService\PurchaseOrderCreationServices\PurchaseOrderService.cs:line 18
at PurchaseOrderCreationServiceApi.Controllers.PurchaseOrderCreationController.Add(PurchaseOrderCreationRequest purchaseOrderCreationRequest) in C:\Projects-Git\Enterprise\PurchaseOrderCreationService\PurchaseOrderCreationServiceApi\Controllers\PurchaseOrderCreationController.cs:line 25

异常消息是:Specified method is not supported.

谁能帮我解决这个错误? .NET Core 2.0 不支持这种方法对我来说没有意义。我已经通过 SqlBulkCopy 在其他 .NET Core 2.0 应用程序中成功使用了 FastMember。但这是我第一次尝试将它与 Dapper 一起使用。

非常感谢任何帮助!提前致谢。

【问题讨论】:

不支持哪种方式? 检查这个分支github.com/dotnet/corefx/issues/24502。可能的错误 “.NET Core 2.0 不支持这种方法对我来说毫无意义。” - 哦,相信我,你不会相信过去在 dotnet github repo 上的论点与此相关......但是! reader 在这段代码中来自哪里?如果您从图片中删除“dapper”并使用ExecuteDataReader,会发生同样的事情吗? (只是为了缩小我们所说的范围) @BenHarris 它是GetSchemaTable(),关于这种方法和 .NET Core 的历史有很多... 我使用的是 Microsoft SQL Server 2012 及更高版本。那么这是一个已知的错误,而我正在尝试做的事情不起作用? 【参考方案1】:

这是 FastMember 的错。基本上,很长一段时间,用于 ADO.NET 的 .NET Core API根本没有提供此 API,这意味着任何针对它的代码无法实现它

此问题现已在较新版本的 .NET Core 中得到纠正,但我未能重新访问 FastMember 以重新添加到 API 中。今晚我将尝试执行此操作,并尽快进行新的部署。

基本上,FastMember 有:

#if !COREFX
    public override DataTable GetSchemaTable()
    ...
#endif

因为:它不能override 一个当时在基类上不存在的方法。


在 v1.2.0 中针对合适的目标平台(包括 netstandard2.0)时已修复此问题

【讨论】:

啊,有道理。非常感谢你的帮助,马克!我将焦急地等待新版本的欢乐到来。 :-) @ChaseHarrison 立即尝试:nuget.org/packages/FastMember/1.2.0 最棒的!它现在就像一个魅力!你大爷!感谢您在发布新版本时非常迅速的周转时间。

以上是关于C# Dapper 和 FastMember - 不支持指定的方法的主要内容,如果未能解决你的问题,请参考以下文章

C# Dapper基本用法

在 C# 中使用 Dapper 读取表的子集

使用C#的DAPPER 进行增删改查操作(准备工作)

C# Dapper基本三层架构使用 (架构关系)

FastMember 将 datagridview CurrentRow 转换回 Object

如何使用 Dapper.NET 将 C# 列表插入数据库