【问题标题】:Casting error on EF Core when calling stored proc on MySQL (using Pomelo)在 MySQL 上调用存储过程时,EF Core 上的转换错误(使用 Pomelo)
【发布时间】:2019-06-02 23:59:25
【问题描述】:

我在使用 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 at lambda_method(Closure, DbDataReader) at Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader 数据读取器)在 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 取消令牌)在 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 取消令牌)在 D:\a\1\s\Ix.NET\Source\System.Interactive.Async\AsyncIterator.cs:line 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 取消令牌)在 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 在 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(状态& next, Scope& 范围, Object& 状态, Boolean& isCompleted) at 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(状态和下一个, 范围&作用域、对象&状态、布尔& isCompleted)在 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");
});

我整天都在绞尽脑汁想弄明白这个……有什么想法吗?

【问题讨论】:

  • 我会检查 SP 是否为一些标记为必需的字符串列(“file_num”或“description”)返回 DbNull。或者把 fluent mapping 中的IsRequired 注释掉,看看是否有效。
  • 我不敢相信我是个白痴!我怎么没看到!非常感谢伊万!
  • 附言。我想将您的回复标记为答案,但我不能,因为它是评论?不知道您是否愿意将其作为回复发布,以便我可以将其标记为答案?...。再次感谢
  • 不客气,很高兴它有帮助:)但这只是一个猜测(在黑暗中拍摄),因此发表评论。随意发布一个自我回答问题是什么以及您如何解决它,我很乐意投票。干杯。

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    正如 Ivan 在评论中提到的,“description”和“file_num”字段是必需的(IsRequired = true)。因为有些行有 DbNulls,所以导致了异常。我取消了这个限制,一切都很好。

    【讨论】:

      猜你喜欢
      • 2017-05-26
      • 2020-03-23
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2019-12-08
      相关资源
      最近更新 更多