【问题标题】:“Property 'System.DateTime Date' is not defined for type 'System.Nullable`1[System.DateTime]' (Parameter 'property')” exception“没有为类型‘System.Nullable`1[System.DateTime]’(参数‘property’)定义属性‘System.DateTime Date’”异常
【发布时间】:2020-12-12 05:14:14
【问题描述】:

将 EF Core 更新到 5.0.1,我在运行测试时遇到了这个异常

导致这种情况的方法如下:

public static IQueryable<CashoutRequest> WhereTransferOrInstitutionTransferStartDate
(
    this IQueryable<CashoutRequest> cashoutRequests, 
    DateTime? date
)
{
    if (date == null) return cashoutRequests;

    var startDate = date.Value.Date;

    return cashoutRequests.Where(cashoutRequest => 
        cashoutRequest.Transfer.CreatedAt.Date >= startDate
        || 
        cashoutRequest.InstitutionTransfer.CreatedAt.Date >= startDate
    );
}

public static IQueryable<CashoutRequest> WhereTransferOrInstitutionTransferEndDate
(
    this IQueryable<CashoutRequest> cashoutRequests, 
    DateTime? date
)
{
    if (date == null) return cashoutRequests;

    var endDate = date.Value.Date;

    return cashoutRequests.Where(cashoutRequest => 
        cashoutRequest.Transfer.CreatedAt.Date <= endDate
        || 
        cashoutRequest.InstitutionTransfer.CreatedAt.Date <= endDate
    );
}

字段CreatedAt 不是nullables。 EF Core 是否可以在运行时将它们转换为可空值?

实体:

public class CashoutRequest
{
  public long Id { get; set; }
  public long? TransferId { get; set; }
  public DateTime CreatedAt { get; set; } = DateTime.Now;
  public DateTime? ReprovedAt { get; set; }
  public DateTime? ApprovedAt { get; set; }
  public DateTime? CanceledAt { get; set; }
  public Transfer Transfer { get; set; }
  public InstitutionTransfer InstitutionTransfer { get; set; }
}

public class Transfer
{
  public long Id { get; set; }
  public DateTime CreatedAt { get; set; } = DateTime.Now;
  public DateTime? ApprovedAt { get; set; }
  public DateTime? CanceledAt { get; set; }
  public DateTime? ReprovedAt { get; set; }
}

public class InstitutionTransfer
{
    public long Id { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.Now;
    public DateTime? ApprovedAt { get; set; }
    public DateTime? CanceledAt { get; set; }
    public DateTime? ReprovedAt { get; set; }
    public long? CashoutRequestId { get; set; }

    public CashoutRequest CashoutRequest { get; set; }
}

PS.:当我删除 .Date 属性时,测试会成功执行

PS².: CashoutRequest.Transfer 和 CashoutRequest.InstitutionTransfer 可以为空,我不知道这是否会导致错误。但是这些方法在更新之前工作正常

堆栈跟踪:

System.ArgumentException: Property 'System.DateTime Date' is not defined for type 'System.Nullable`1[System.DateTime]' (Parameter 'property')
   at System.Linq.Expressions.Expression.Property(Expression expression, PropertyInfo property)
   at System.Linq.Expressions.Expression.MakeMemberAccess(Expression expression, MemberInfo member)
   at System.Linq.Expressions.MemberExpression.Update(Expression expression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryExpressionTranslatingExpressionVisitor.VisitMember(MemberExpression memberExpression)
   at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryExpressionTranslatingExpressionVisitor.VisitBinary(BinaryExpression binaryExpression)
   at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryExpressionTranslatingExpressionVisitor.VisitBinary(BinaryExpression binaryExpression)
   at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryExpressionTranslatingExpressionVisitor.TranslateInternal(Expression expression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryExpressionTranslatingExpressionVisitor.Translate(Expression expression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.TranslateExpression(Expression expression, Boolean preserveType)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.TranslateLambdaExpression(ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression, Boolean preserveType)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryQueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at api.Controllers.Employee.TransfersController.TransferList(TransferFiltersModel model) in D:\Pagcerto\API\PaymentAccount\src\api\Controllers\Employee\TransfersController.cs:line 49
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()

类映射:

public static void Map(this EntityTypeBuilder<CashoutRequest> entity)
{
    entity.ToTable("SolicitacaoTransferencia", "financeiro");

    entity.Property(p => p.Id).UseIdentityColumn();
    entity.Property(p => p.CreatedAt.IsRequired();
    entity.Property(p => p.ReprovedAt);
    entity.Property(p => p.ApprovedAt);
    entity.Property(p => p.CanceledAt);
    entity.Property(p => p.TransferId);
}

public static void Map(this EntityTypeBuilder<Transfer> entity)
{
    entity.HasKey(p => p.Id);

    entity.Property(p => p.Id).UseIdentityColumn();
    entity.Property(p => p.CreatedAt).IsRequired();
    entity.Property(p => p.ApprovedAt);
    entity.Property(p => p.CanceledAt);
    entity.Property(p => p.ReprovedAt);

    entity.HasOne(p => p.CashoutRequest).WithOne(p => p.Transfer).HasForeignKey<CashoutRequest>(p => p.TransferId).OnDelete(DeleteBehavior.Restrict);
}

public static void Map(this EntityTypeBuilder<InstitutionTransfer> entity)
{
    entity.HasKey(p => p.Id);

    entity.Property(p => p.Id).HasColumnName("Id").UseIdentityColumn();
    entity.Property(p => p.CreatedAt).IsRequired();
    entity.Property(p => p.ApprovedAt);
    entity.Property(p => p.CanceledAt);
    entity.Property(p => p.ReprovedAt);
    entity.Property(p => p.CashoutRequestId);

    entity.HasOne(p => p.CashoutRequest).WithOne(p => p.InstitutionTransfer).HasForeignKey<InstitutionTransfer>(p => p.CashoutRequestId).OnDelete(DeleteBehavior.Restrict);
}

【问题讨论】:

  • 这不是一个答案,但你能检查一下数据库是否可以为空吗?或者如果可以的话检查迁移代码...?
  • @Ergis 这些属性在迁移或数据库中都不能为空
  • 您能否将完整的异常消息添加到问题中?
  • @RufusL 消息就是这样。你是说堆栈跟踪吗?
  • @RufusL 添加了堆栈跟踪

标签: c# entity-framework-core


【解决方案1】:

很高兴你让它工作了,但就它可能发生的原因而言,我在聊天中提到这可能是由于this breaking change。它之前可能永远无法评估 linq 表达式,但在旧版本的 EF Core 中,它会尝试获取所有行并在客户端对其进行评估(这非常昂贵!)。因此,微软最终决定取消这一点。

最好在与生产中使用的数据库非常相似的数据库上运行测试,否则无论如何它都不会真正经过全面测试。来自微软的This article 在这一点上讲了更多。它还提到了内存数据库的一些限制。

一般来说,解决此类问题的最佳方法是记下您从哪个版本的 EF Core 升级以及升级到哪个版本。然后,您需要查看每次升级之间的所有重大更改,看看是否有适用的。

【讨论】:

    【解决方案2】:

    我在 prod 上对此进行了测试,它确实有效。所以我将 InMemoryDatabase 更改为 SQLite,这个测试通过了,但另外 59 个测试失败了。我现在会努力修复它们

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-05
      • 2017-12-30
      • 2017-05-05
      • 1970-01-01
      相关资源
      最近更新 更多