EF Core 3.1 调用 context.Add() 在使用 SQL 中的序列的模型上抛出 "nullable object must have a value"
EF Core 3.1 calling context.Add() throws "nullable object must have a value" on models that utilize sequences in SQL
我正在尝试将 asp.net 核心项目从 2.2 迁移到 3.1,因此我也必须从 EF Core 2.2 升级到 EF Core 3.1。
我尝试直接升级 2.2 项目并失败,然后创建了一个新项目,复制了我的模型和 DbContext,现在在任何调用 MyDbContext.Add() 时出现 "nullable object must have a value" 错误使用 SQL 中的序列生成一些值的模型。
任何不使用序列的模型都不会发生此错误,我可以在这些模型上调用 add 就好了。
我尝试使用的模型看起来像这样:
(请注意,我已重命名每个 属性 并删除了多次使用的数据类型)
public class MyModel
{
public int Id { get; set; }
private DateTime? timeStamp;
public DateTime TimeStamp
{
get { return timeStamp ?? DateTime.UtcNow; }
set { timeStamp = value; }
}
public int MySequence { get; private set; }
public string MySequenceWithPrefix
{
get
{
return "Prefix" + MySequence.ToString()
}
}
public MyEnumType EnumType { get; set; }
public string StringValue { get; set; }
public bool? NullableBoolean { get; set; }
public bool NotNullableBoolean { get; set; }
public int? NullableFK { get; set; } //For the below navigation property
public MyNavigationProperty NavigationProperty { get; set; }
public ICollection<MyCollectionOfThings> Things { get; set; }
public DateTime? NullableDateTime { get; set; }
public MyNullableEnumProperty? NullableEnumProperty { get; set; }
[DataType(DataType.Currency)] public double? NullableCurrencyField { get; set; }
}
我在模型构建器中配置了这样的序列:
modelBuilder.HasSequence<int>("MySequence")
.StartsAt(40000)
.IncrementsBy(1);
modelBuilder.Entity<MyModel>()
.Property(model => model.MySequence)
.HasDefaultValueSql("NEXT VALUE FOR MySequence");
我正在尝试这样调用 MyDbContext.Add():
MyModel testMyModel = new MyModel()
{
//set non-nullable fields here
};
//throws "Nullable object must have a value."
MyDbContext.Add(testMyModel);
我不确定从 EF Core 2.2 到 3.1 是否有涉及序列的重大变化,或者我在创建新项目和手动移动模型时是否设置不正确。
如果您需要任何进一步的信息,请告诉我。
编辑:
带有堆栈跟踪的完整错误消息是这样的:
InvalidOperationException: Nullable object must have a value.
System.Nullable<T>.get_Value()
lambda_method(Closure , InternalEntityEntry )
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry+OriginalValues..ctor(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.EnsureOriginalValues()
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntrySubscriber.SnapshotAndSubscribe(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, bool acceptChanges, bool modifyProperties)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, bool acceptChanges, bool modifyProperties, Nullable<EntityState> forceStateWhenUnknownKey)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode<ValueTuple<EntityState, EntityState, bool>> node)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph<TState>(EntityEntryGraphNode<TState> node, Func<EntityEntryGraphNode<TState>, bool> handleNode)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, bool forceStateWhenUnknownKey)
Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)
Microsoft.EntityFrameworkCore.DbContext.SetEntityState<TEntity>(TEntity entity, EntityState entityState)
Microsoft.EntityFrameworkCore.DbContext.Add<TEntity>(TEntity entity)
MyProject.Areas.MyArea.Controllers.MyController.Form(FormValues values) in MyController.cs
MyDbContext.Add(testMyModel);
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
如果堆栈跟踪太长,请提前致歉。我不知道你需要什么信息。
问题出在您的 TimeStamp
属性 上。尝试用 NotMappedAttribute
标记它,错误就会消失。我无法解释是什么内部 EF 魔法使它以这种方式运行,但我个人强烈建议不要在 EF 模型中使用 "non-trivial" 属性,例如您的 TimeStamp
模型。
UPD
似乎 EF 认为 private DateTime? timeStamp;
是 TimeStamp
属性 的支持字段,尽管 documentation saying that backing filed should start with _
or m_
, but 回答指出驼峰式属性也有效,并且重命名 timeStamp
到 timeStampss
之类的东西也会使错误消失。
我正在尝试将 asp.net 核心项目从 2.2 迁移到 3.1,因此我也必须从 EF Core 2.2 升级到 EF Core 3.1。
我尝试直接升级 2.2 项目并失败,然后创建了一个新项目,复制了我的模型和 DbContext,现在在任何调用 MyDbContext.Add() 时出现 "nullable object must have a value" 错误使用 SQL 中的序列生成一些值的模型。
任何不使用序列的模型都不会发生此错误,我可以在这些模型上调用 add 就好了。
我尝试使用的模型看起来像这样:
(请注意,我已重命名每个 属性 并删除了多次使用的数据类型)
public class MyModel
{
public int Id { get; set; }
private DateTime? timeStamp;
public DateTime TimeStamp
{
get { return timeStamp ?? DateTime.UtcNow; }
set { timeStamp = value; }
}
public int MySequence { get; private set; }
public string MySequenceWithPrefix
{
get
{
return "Prefix" + MySequence.ToString()
}
}
public MyEnumType EnumType { get; set; }
public string StringValue { get; set; }
public bool? NullableBoolean { get; set; }
public bool NotNullableBoolean { get; set; }
public int? NullableFK { get; set; } //For the below navigation property
public MyNavigationProperty NavigationProperty { get; set; }
public ICollection<MyCollectionOfThings> Things { get; set; }
public DateTime? NullableDateTime { get; set; }
public MyNullableEnumProperty? NullableEnumProperty { get; set; }
[DataType(DataType.Currency)] public double? NullableCurrencyField { get; set; }
}
我在模型构建器中配置了这样的序列:
modelBuilder.HasSequence<int>("MySequence")
.StartsAt(40000)
.IncrementsBy(1);
modelBuilder.Entity<MyModel>()
.Property(model => model.MySequence)
.HasDefaultValueSql("NEXT VALUE FOR MySequence");
我正在尝试这样调用 MyDbContext.Add():
MyModel testMyModel = new MyModel()
{
//set non-nullable fields here
};
//throws "Nullable object must have a value."
MyDbContext.Add(testMyModel);
我不确定从 EF Core 2.2 到 3.1 是否有涉及序列的重大变化,或者我在创建新项目和手动移动模型时是否设置不正确。
如果您需要任何进一步的信息,请告诉我。
编辑: 带有堆栈跟踪的完整错误消息是这样的:
InvalidOperationException: Nullable object must have a value.
System.Nullable<T>.get_Value()
lambda_method(Closure , InternalEntityEntry )
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry+OriginalValues..ctor(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.EnsureOriginalValues()
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntrySubscriber.SnapshotAndSubscribe(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, bool acceptChanges, bool modifyProperties)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, bool acceptChanges, bool modifyProperties, Nullable<EntityState> forceStateWhenUnknownKey)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode<ValueTuple<EntityState, EntityState, bool>> node)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph<TState>(EntityEntryGraphNode<TState> node, Func<EntityEntryGraphNode<TState>, bool> handleNode)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, bool forceStateWhenUnknownKey)
Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)
Microsoft.EntityFrameworkCore.DbContext.SetEntityState<TEntity>(TEntity entity, EntityState entityState)
Microsoft.EntityFrameworkCore.DbContext.Add<TEntity>(TEntity entity)
MyProject.Areas.MyArea.Controllers.MyController.Form(FormValues values) in MyController.cs
MyDbContext.Add(testMyModel);
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()
System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
如果堆栈跟踪太长,请提前致歉。我不知道你需要什么信息。
问题出在您的 TimeStamp
属性 上。尝试用 NotMappedAttribute
标记它,错误就会消失。我无法解释是什么内部 EF 魔法使它以这种方式运行,但我个人强烈建议不要在 EF 模型中使用 "non-trivial" 属性,例如您的 TimeStamp
模型。
UPD
似乎 EF 认为 private DateTime? timeStamp;
是 TimeStamp
属性 的支持字段,尽管 documentation saying that backing filed should start with _
or m_
, but timeStamp
到 timeStampss
之类的东西也会使错误消失。