tmsmith / Dapper-Extensions

Dapper Extensions is a small library that complements Dapper by adding basic CRUD operations (Get, Insert, Update, Delete) for your POCOs. For more advanced querying scenarios, Dapper Extensions provides a predicate system. The goal of this library is to keep your POCOs pure by not requiring any attributes or base class inheritance.
1.79k stars 586 forks source link

Unable to set my mapper class as the mapper that is used to insert an object into a table #319

Open pol1612 opened 1 year ago

pol1612 commented 1 year ago

So here I have my mapper class: `using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Dapper.Core.Entities; using DapperExtensions.Mapper;

namespace Dapper.Infrastructure.Mappers { public class DeviceMapper : ClassMapper { public DeviceMapper() { //throw new NotImplementedException();
Schema("dbo"); Table("Devices"); Console.WriteLine("it maps"); AutoMap(); } } } Here is the Device object: namespace Dapper.Core.Entities { public class Device { public Guid? Id { get; set; } public string? Name { get; set; } public string? TelemetryType { get; set; }

    public Device()
    {

    }
    public Device(string name, string telemetryType, Guid? id = null)
    {
        Id = id ?? Guid.NewGuid();
        Name = name;
        TelemetryType = telemetryType;
    }
}

} Here is where is set the mapper and try to insert the object: public async Task AddAsync(Device entity) {

        using (IDbConnection db = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
        {
            DapperExtensions.DapperAsyncExtensions.DefaultMapper = typeof(DeviceMapper);
            DapperExtensions.DapperExtensions.SetMappingAssemblies
            (
                new[] { typeof(DeviceMapper).Assembly }
            );

            db.Open();

            Guid id = await db.InsertAsync<Device>(entity);

            return id;
        }
    }

` And here is how the devices table looks like: image

And here is the exception that is thrown when i execute this code: System.InvalidOperationException HResult=0x80131509 Message=Dapper.Infrastructure.Mappers.DeviceMapper is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true. Source=System.Private.CoreLib StackTrace: at System.RuntimeType.MakeGenericType(Type[] instantiation) at DapperExtensions.DapperExtensionsConfiguration.GetMap(Type entityType) at DapperExtensions.DapperAsyncImplementor.<InsertAsync>d__21.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Dapper.Infrastructure.Repositories.DeviceRepository.<AddAsync>d__2.MoveNext() in C:\Users\psane\source\repos\C#\Dapper.WebApi\Dapper.Infrastructure\Repositories\DeviceRepository.cs:line 46 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Dapper.WebApi.Controllers.DeviceController.d__4.MoveNext() in C:\Users\psane\source\repos\C#\Dapper.WebApi\Dapper.WebApi\Controllers\DeviceController.cs:line 42

This exception was originally thrown at this call stack: [External Code] Dapper.Infrastructure.Repositories.DeviceRepository.AddAsync(Dapper.Core.Entities.Device) in DeviceRepository.cs [External Code] Dapper.WebApi.Controllers.DeviceController.Post(Dapper.Core.Entities.Device) in DeviceController.cs`

kpanpfizer commented 1 year ago

Hi, I think Default mapper must be generic to handle any type You try to use. So just don't register any if you do not need to change Dapper Extension default conventions.

Also You are registering your mapper in wrong extensions (DapperExtensions instead of DapperAsyncExtensions) thats why it is not beeing called.

This should work:

using (IDbConnection db = new SqlConnection(_configuration.GetConnectionString("DefaultConnection")))
        {
            DapperExtensions.**DapperAsyncExtensions**.SetMappingAssemblies
            (
                new[] { typeof(DeviceMapper).Assembly }
            );

            db.Open();

            Guid id = await db.InsertAsync<Device>(entity);

            return id;
        }

Also You can do it once at the start of application no need to do it every time (maybe that is clear to You and it was just example code).