Ошибка приведения в EF Core при вызове хранимой процедуры на MySQL (с использованием Pomelo)

У меня проблема с веб-API.Net Core 2.2, использующим EF Core. Я вызываю хранимую процедуру в базе данных MySQL (я использую Pomelo 2.1.4).

Он жалуется на невозможность конвертировать из DbNull в String:

Ошибка: невозможно преобразовать объект типа "System.DBNull" в тип "System.String". по адресу MySql.Data.MySqlClient.MySqlDataReader.GetString(порядковый номер Int32) в C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs: строка 210 в хранилище данных SharePoint; Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader) в Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 операции, Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable1.AsyncEnumerator.MoveNext(CancellationToken cancellationToken) в System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator2.MoveNextCore(CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Select.cs:line 106
at System.Linq.AsyncEnumerable.AsyncIterator
1.MoveNext(CancellationToken cancellationToken) в D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs: строка 98 в Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken) at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable1 источник, TAccumulate семя, Func3 accumulator, Func2 resultSelector, CancellationToken cancellationToken) в D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Aggregate.cs: строка 120 в PropWorx.API.Controllers.FileActivitiesController.GetFileActivities(Int32 fileId, String from, String toDate) в C:\Users\fabsr\source\repos\PropWorx.API\PropWorx.API\Controllers\FileActivitiesController.cs: строка 101 в Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExypper. Исполнитель ObjectMethodExecutor, Контроллер объекта, аргументы Object [] в System.Threading.Tasks.ValueTask`1.get_Result () в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync () в Microsoft.AspNetCternalInont.ont.v. InvokeNextActionFilterAsync () в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow (контекст ActionExecutedContext) в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State & next, Scope & scope, Object & state, BooC, Object & state, BooC,) в Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() в Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() в Microsoft.AspNetCore.Mvc.Internal.RecureContainer.Mvc.Internal.ResourceInvoker.Next(Состояние и следующее, Область и область действия, Объект и состояние, Булево и isCompleted) в Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() в Microsoft.AspNetCore.Mvc.Internal.InesInvvoker)
в Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) в Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) в PropWorx.API.Middlewares.TenantxtteteteteteteteteInIn. \fabsr\source\repos\PropWorx.API\PropWorx.API\Middlewares\TenantIdentifier.cs: строка 73 в Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(контекст HttpContext) в Microsoft.AspNetCore.Builder.Exhen Вызвать (контекст HttpContext) в Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(контекст HttpContext) в Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpConteger Http. Http: в Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke (контекст HttpContext) в Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware. Invoke (контекст HttpContext)

Проблемная линия:

List<FileActivity> fileActivities = await _context.FileActivities.FromSql("CALL file_activity_procedure(@fromDate, @toDate, @fileId)", param1, param2, param3).ToListAsync();

модель FileActivity:

public class FileActivity
{
    public int Id { get; set; }
    public DateTime? Date { get; set; }
    public int FileId { get; set; }
    public string FileNumber { get; set; }
    public string Area { get; set; }
    public int? RecordId { get; set; }
    public string Description { get; set; }
    public string Type { get; set; }
    public string TypeInfo { get; set; }
    public decimal? Debit { get; set; }
    public decimal? Credit { get; set; }
    public string AddedBy { get; set; }
    public DateTime? AddedDate { get; set; }
    public string Comments { get; set; }
}

И, наконец, отображение в DbContext:

modelBuilder.Entity<FileActivity>(entity =>
{
    entity.Property(e => e.Id)
        .HasColumnName("ID")
        .HasColumnType("int(11)");

    entity.Property(e => e.Date)
        .HasColumnName("Date")
        .HasColumnType("datetime");

    entity.Property(e => e.FileId)
        .HasColumnName("file_id")
        .HasColumnType("int(11)");

    entity.Property(e => e.FileNumber)
        .IsRequired()
        .HasColumnName("file_num")
        .HasColumnType("varchar(50)");

    entity.Property(e => e.Description)
        .IsRequired()
        .HasColumnName("description")
        .HasColumnType("varchar(255)");

    entity.Property(e => e.Type)
        .HasColumnName("type")
        .HasColumnType("varchar(255)");

    entity.Property(e => e.TypeInfo)
        .HasColumnName("type_info")
        .HasColumnType("varchar(255)");

    entity.Property(e => e.Debit)
       .HasColumnName("Debit")
       .HasColumnType("decimal(13,4)")
       .HasDefaultValueSql("'0.0000'");

    entity.Property(e => e.Credit)
       .HasColumnName("Credit")
       .HasColumnType("decimal(13,4)")
       .HasDefaultValueSql("'0.0000'");

    entity.Property(e => e.RecordId)
       .HasColumnName("record_id")
       .HasColumnType("int(11)");

    entity.Property(e => e.AddedBy)
        .HasColumnName("Added_By")
        .HasColumnType("varchar(45)");

    entity.Property(e => e.AddedDate)
        .HasColumnName("added_date")
        .HasColumnType("datetime");

    entity.Property(e => e.Comments)
        .HasColumnName("comment")
        .HasColumnType("text");
});

Я весь день ломал свой мозг, пытаясь выяснить это... Есть идеи?

1 ответ

Как отметил Иван в комментарии, поля "description" и "file_num" были обязательными (IsRequired = true). Поскольку некоторые строки имели DbNulls, это вызвало исключение. Я снял это ограничение, и все было хорошо.

Проблема в том, что те свойства, которые не требуются в modelBuilder, должны быть определены как обнуляемые в ваших сущностях и моделях с помощью?. Подобно FileId, и это потому, что если в таблице есть запись с нулевым значением для этих полей, то он вернет нулевое значение в вашем классе сущности, но ваш класс сущности не может принять нулевое значение для этих ненулевых свойств и затем выбрасывает ошибка.

Другие вопросы по тегам