简体   繁体   中英

C# Dapper and FastMember - Specified method not supported

I have a C# .NET Core 2.0 Web API project (implemented as a microservice).

I am using NuGet Packages "Dapper" and "FastMember" (latest versions) in my repository layer to try to convert an IEnumerable<T> to a DataTable via the ObjectReader that FastMember provides, so that I can take advantage of Dapper's built-in ICustomQueryParameter SqlMapper to pass a table-valued parameter to a stored procedure that I am using in SQL Server.

When I execute and debug my code, it throws an exception on the line where the FastMember ObjectReader attempts to be loaded into a DataTable: table.Load(reader); .

Here is my Dapper wrapper/extension method that contains the problematic line:

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);
        }
}

Here is my Dapper call that uses the above extension method:

using (var dbConnection = new SqlConnection(_connectionString))
{
    var result = dbConnection.Query("[PurchaseOrders].[Add] @tvpNewPurchaseOrderItems, @StartDate", new
    {
        tvpNewPurchaseOrderItems = purchaseOrderCreationRequest.PurchaseOrderItems.AsTvp("NewPurchaseOrderType"),
    StartDate = purchaseOrderCreationRequest.StartDate
    });
}

And here is the stack trace from my C# exception that was thrown:

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

Exception message was: Specified method is not supported.

Can anybody help me with this error?? It doesn't make sense to me that .NET Core 2.0 wouldn't support this method. And I have used FastMember in other .NET Core 2.0 apps successfully with SqlBulkCopy. But this is the first time that I've tried using it with Dapper.

Any help is much appreciated! Thanks in advance.

This is FastMember's fault. Basically, for a very long time , the .NET Core API for ADO.NET didn't provide this API at all , which meant that any code targeting it could not implement it .

This has now been rectified in newer versions of .NET Core, but I have failed to revisit FastMember to add back in the API. I will try to do this tonight and get a new deployment out ASAP.

Essentially, FastMember has:

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

because: it couldn't override a method that didn't exist on the base class at the time.


This has been fixed in v1.2.0 when targeting suitable target platforms including netstandard2.0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM