在MySQL(使用Pomelo)上调用存储的proc时,在EF Core上投射错误

时间:2019-01-08 10:00:58

标签: .net-core asp.net-core-webapi pomelo ef-core-2.2

使用EF Core的.Net Core 2.2 Web API出现问题。我正在MySQL数据库上调用存储过程(我正在使用Pomelo 2.1.4)。

它抱怨无法从DbNull转换为String:

  

错误:无法转换类型为'System.DBNull'的对象来键入   “ System.String”。   MySql.Data.MySqlClient.MySqlDataReader.GetString(Int32 ordinal)在   C:\ projects \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs:line   210在lambda_method(Closure,DbDataReader)在   Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader   dataReader)   Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable 1.AsyncEnumerator.BufferlessMoveNext(DbContext _, Boolean buffer, CancellationToken cancellationToken) at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func 4操作,Func 4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable 1.AsyncEnumerator.MoveNext(CancellationToken   cancelToken)   System.Linq.AsyncEnumerable.SelectEnumerableAsyncIterator 2.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   cancelToken)在   D:\ a \ 1 \ s \ Ix.NET \ Source \ System.Interactive.Async \ AsyncIterator.cs:line   98岁   Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor 1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken) at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable 1   来源,TAccumulate种子,Func 3 accumulator, Func 2 resultSelector,   CancellationToken CancellationToken)中   D:\ a \ 1 \ s \ Ix.NET \ Source \ System.Interactive.Async \ Aggregate.cs:第120行   在   PropWorx.API.Controllers.FileActivitiesController.GetFileActivities(Int32   fileId,字符串fromDate,字符串toDate)   C:\ Users \ fabsr \ source \ repos \ PropWorx.API \ PropWorx.API \ Controllers \ FileActivitiesController.cs:line   101 at   Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper   映射器,ObjectMethodExecutor执行器,对象控制器,Object []   参数)位于System.Threading.Tasks.ValueTask`1.get_Result()处   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()   在   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()   在   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext   上下文)   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State&   接下来,范围和作用域,对象和状态,布尔值和isCompleted)位于   Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()   在   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()   在   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext   上下文)   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State&next,   范围和范围,对象和状态,布尔值和完成)位于   Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()   在Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
  在Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext   httpContext)   Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext   httpContext)   PropWorx.API.Middlewares.TenantIdentifier.Invoke(HttpContext   httpContext,SharedContext sharedContext)中   C:\ Users \ fabsr \ source \ repos \ PropWorx.API \ PropWorx.API \ Middlewares \ TenantIdentifier.cs:line   73在   Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext   上下文)   Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext   上下文)   Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext   上下文)   Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext   httpContext)   Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext   httpContext,ISwaggerProvider swaggerProvider)位于   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");
});

我整天都在动脑筋,想办法解决这个问题...有什么想法吗?

2 个答案:

答案 0 :(得分:1)

如Ivan在评论中所述,“ description”和“ file_num”字段是必填字段(IsRequired = true)。由于某些行具有DbNulls,因此导致异常。我取消了该限制,一切都很好。

答案 1 :(得分:0)

问题在于,必须在带有?的实体和模型中将modelBuilder中不需要的那些属性定义为可空的。就像FileId一样,这是因为如果表中的记录中那些字段的值为空,那么它将在您的实体类中返回null,但是您的实体类不能为那些不可为空的属性接受空值,然后它将抛出错误。