简体   繁体   中英

“Property 'System.DateTime Date' is not defined for type 'System.Nullable`1[System.DateTime]' (Parameter 'property')” exception

Updated EF Core to 5.0.1 and I got this exception when I ran the tests

The methods that cause this are these:

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
    );
}

The fields CreatedAt aren't nullables . Is possible for EF Core to turn them into nullables in runtime?

Entities:

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.: When I remove.Date property the test execute with success

PS².: CashoutRequest.Transfer and CashoutRequest.InstitutionTransfer can be null, I don't know if this can cause the error. But these methods was working ok before the update

Stacktrace:

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()

Class mappings:

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);
}

Glad you got it working but in terms of why it may have happened I mentioned in chat that it is likely due to this breaking change . It may never have been able to evaluate the linq expression prior but in older editions of EF Core it would then try to take all the rows and evaluate it on the client side (which is super expensive.), Hence. Microsoft finally decided to pull the plug on this.

It is always better to run a test on databases that are very similar to the ones used in production otherwise it won't really be fully tested anyway. This article from Microsoft speaks a little more on this point. It also mentions a number of limitations of the in memory database.

As a general note, the best way to approach these types of problems is to take note of which version of EF Core you upgraded from and which version you upgraded to. Then you want to review all the breaking changes between each upgrade to see if any might apply.

I tested this on prod and it worked. So I changed the InMemoryDatabase to SQLite and this test passed, but another 59 tests broken. I'll work to fix them now

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM