Entity Framework Core:“SqlNullValueException:数据为 Null”。 如何排除故障?

Entity Framework Core: `SqlNullValueException: Data is Null.` How to troubleshoot?

提问人:Natalie Perret 提问时间:4/28/2019 最后编辑:Natalie Perret 更新时间:10/6/2023 访问量:203873

问:

我在 ASP.NET Core 应用程序和控制器操作中使用 Entity Framework Core,我没有对工作代码或数据库进行任何更改,但我无法判断 Entity Framework Core 执行的查询是什么。

控制器操作:

[HttpGet]
// GET: Administration/Companies
public async Task<ActionResult> Index()
{
    var users = await UserManager.Users.ToListAsync();

    var companyEditVMs = await DB.Companies
    .OrderBy(company => company.CompanyId == 1 
        ? "_" + company.CompanyName 
        : company.CompanyName
    )
    Select(a => new CompanyEditVM(HttpContext, a, users.Where(b => b.CompanyId == a.CompanyId)))
    .ToListAsync();

    return View(companyEditVMs);
}

跟踪

SqlNullValueException: Data is Null. This method or property cannot be called on Null values.
System.Data.SqlClient.SqlBuffer.get_String()
System.Data.SqlClient.SqlDataReader.GetString(int i)
lambda_method(Closure , DbDataReader )
Microsoft.EntityFrameworkCore.Storage.Internal.TypedRelationalValueBufferFactory.Create(DbDataReader dataReader)
Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable<T>+AsyncEnumerator.BufferlessMoveNext(DbContext _, bool buffer, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync<TState, TResult>(TState state, Func<DbContext, TState, CancellationToken, Task<TResult>> operation, Func<DbContext, TState, CancellationToken, Task<ExecutionResult<TResult>>> verifySucceeded, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.AsyncQueryingEnumerable<T>+AsyncEnumerator.MoveNext(CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider+ExceptionInterceptor<T>+EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken)
System.Linq.AsyncEnumerable.Aggregate_<TSource, TAccumulate, TResult>(IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken) in Aggregate.cs
KYC.Core.Areas.Commercial.Controllers.CompaniesController.Index() in CompaniesController.cs
-
        [HttpGet]
        // GET: Administration/Companies
        public async Task<ActionResult> Index()
        {
            var users = await UserManager.Users.ToListAsync();

            var companyEditVMs = await DB.Companies
                .OrderBy(company => company.CompanyId == 1 
                    ? "_" + company.CompanyName 
                    : company.CompanyName
                )
                .Select(a => new CompanyEditVM(HttpContext, a, users.Where(b => b.CompanyId == a.CompanyId)))
                .ToListAsync();
lambda_method(Closure , object )
Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable+Awaiter.GetResult()
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()

我什至试着做.我也有完全相同的例外。var companies = await DB.Companies.ToListAsync()

也许我希望能够获取 EF Core 执行的查询以手动执行此操作,以便我可以尝试找出查询的问题。

我想知道可能会发生什么。特别是因为其他实体(如用户或国家/地区)仍然可以从数据库中获取。

知道如何解决实际的潜在问题吗?

[编辑]

“代码”中唯一实际更改的是 nuget 引用,我基本上升级了几乎所有内容,尽管它没有破坏代码中的引用,但它似乎改变了 EF Core 以某种方式(疯狂猜测)解释数据库的方式。

我确实将我的 git 存储库重置到nuget包更新发生之前的程度,并且一切正常。然后我决定将 EntityFrameworkCore 从 2.0.2 更新到 2.2.4(也尝试过 2.2.0 并最终得到相同的结果),问题再次发生......不确定 2.0.2 和 2.2.0 之间发生了什么变化来触发此异常(但模型相同,只是 EF Core 版本发生了变化)...

这是实体定义,它似乎是使用数据库表/模式中的工具自动生成的:


    [Table("T_Companies")]
    public partial class Company : INotifyPropertyChanging, INotifyPropertyChanged
    {
        public override string ToString()
        {
            return CompanyId + " " + CompanyName;
        }

        private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(string.Empty);

        private int _CompanyId;

        private string _CompanyName;

        private int _CompanyTypeId;

        private int _CountryId;

        private string _CompanyVatNumber;

        private string _CompanyStreetAddress;

        private string _CompanyZipCode;

        private string _CompanyCity;

        private string _ContactLastName;

        private string _ContactFirstName;

        private bool? _Active;

        private int? _AccountId;

        private string _CallbackSalt;

        private int? _UserSpaceId;

        private string _Login;

        private string _Pwd;

        private bool _IsTechnicalAccount;

        private DateTime? _StatusDate;

        private int _BankStatusCode;

        private string _PivotalAccount;

        private CompanyType _CompanyType;

        private Country _Country;

        private bool _IsKycIdSent;

        #region Extensibility Method Definitions
        partial void OnLoaded();
        partial void OnCreated();
        partial void OnCompanyIdChanging(int value);
        partial void OnCompanyIdChanged();
        partial void OnCompanyNameChanging(string value);
        partial void OnCompanyNameChanged();

        partial void OnCompanyCityChanging(string value);
        partial void OnCompanyCityChanged();
        partial void OnCompanyZipCodeChanging(string value);
        partial void OnCompanyZipCodeChanged();
        partial void OnContactLastNameChanging(string value);
        partial void OnContactLastNameChanged();
        partial void OnActiveChanging(bool? value);
        partial void OnActiveChanged();
        partial void OnCompanyTypeIdChanging(int value);
        partial void OnCompanyTypeIdChanged();
        partial void OnCountryIdChanging(int value);
        partial void OnCountryIdChanged();
        partial void OnContactFirstNameChanging(string value);
        partial void OnContactFirstNameChanged();
        partial void OnCompanyVatNumberChanging(string value);
        partial void OnCompanyVatNumberChanged();
        partial void OnCompanyStreetAddressChanged();
        partial void OnCompanyStreetAddressChanging(string value);
        partial void OnAccountIdChanging(int? value);
        partial void OnAccountIdChanged();
        partial void OnCallbackSaltChanging(string value);
        partial void OnCallbackSaltChanged();
        partial void OnUserSpaceIdChanging(int? value);
        partial void OnUserSpaceIdChanged();
        partial void OnLoginChanging(string value);
        partial void OnLoginChanged();
        partial void OnPwdChanging(string value);
        partial void OnPwdChanged();
        partial void OnIsTechnicalAccountChanging(bool value);
        partial void OnIsTechnicalAccountChanged();
        partial void OnStatusDateChanging(DateTime? value);
        partial void OnStatusDateChanged();
        partial void OnBankStatusCodeChanging(int value);
        partial void OnBankStatusCodeChanged();
        partial void OnPivotalAccountChanging(string value);
        partial void OnPivotalAccountChanged();
        partial void OnIsKycIdSentChanging(bool value);
        partial void OnIsKycIdSentChanged();

        #endregion

        public Company()
        {
            OnCreated();
        }

        [Key, Column("CompanyId"), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int CompanyId
        {
            get => _CompanyId;
            set
            {
                if (_CompanyId != value)
                {
                    OnCompanyIdChanging(value);
                    SendPropertyChanging();
                    _CompanyId = value;
                    SendPropertyChanged("CompanyId");
                    OnCompanyIdChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("CompanyName"), Required]
        public string CompanyName
        {
            get => _CompanyName;
            set
            {
                if (_CompanyName != value)
                {
                    OnCompanyNameChanging(value);
                    SendPropertyChanging();
                    _CompanyName = value;
                    SendPropertyChanged("CompanyName");
                    OnCompanyNameChanged();
                }
            }
        }

        [Column("CompanyTypeId"), Required]
        public int CompanyTypeId
        {
            get => _CompanyTypeId;
            set
            {
                if (_CompanyTypeId != value)
                {
                    OnCompanyTypeIdChanging(value);
                    SendPropertyChanging();
                    _CompanyTypeId = value;
                    SendPropertyChanged("CompanyTypeId");
                    OnCompanyTypeIdChanged();
                }
            }
        }


        [Column("CountryId"), Required]
        public int CountryId
        {
            get => _CountryId;
            set
            {
                if (CountryId != value)
                {
                    OnCountryIdChanging(value);
                    SendPropertyChanging();
                    _CountryId = value;
                    SendPropertyChanged("CountryId");
                    OnCountryIdChanged();
                }
            }
        }


        [DataType(DataType.Text), StringLength(100), Column("CompanyCity"), Required]
        public string CompanyCity
        {
            get => _CompanyCity;
            set
            {
                if (_CompanyCity != value)
                {
                    OnCompanyCityChanging(value);
                    SendPropertyChanging();
                    _CompanyCity = value;
                    SendPropertyChanged("CompanyCity");
                    OnCompanyCityChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(100), Column("CompanyStreetAddress"), Required]
        public string CompanyStreetAddress
        {
            get => _CompanyStreetAddress;
            set
            {
                if (_CompanyStreetAddress != value)
                {
                    OnCompanyStreetAddressChanging(value);
                    SendPropertyChanging();
                    _CompanyStreetAddress = value;
                    SendPropertyChanged("CompanyStreetAddress");
                    OnCompanyStreetAddressChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(30), Column("CompanyVatNumber"), Required]
        public string CompanyVatNumber
        {
            get => _CompanyVatNumber;
            set
            {
                if (_CompanyVatNumber != value)
                {
                    OnCompanyVatNumberChanging(value);
                    SendPropertyChanging();
                    _CompanyVatNumber = value;
                    SendPropertyChanged("CompanyVatNumber");
                    OnCompanyVatNumberChanged();
                }
            }
        }


        [DataType(DataType.Text), StringLength(10), Column("CompanyZipCode"), Required]
        public string CompanyZipCode
        {
            get => _CompanyZipCode;
            set
            {
                if (_CompanyZipCode != value)
                {
                    OnCompanyZipCodeChanging(value);
                    SendPropertyChanging();
                    _CompanyZipCode = value;
                    SendPropertyChanged("CompanyZipCode");
                    OnCompanyZipCodeChanged();
                }
            }
        }


        [DataType(DataType.Text), StringLength(1024), Column("ContactLastName"), Required]
        public string ContactLastName
        {
            get => _ContactLastName;
            set
            {
                if (_ContactLastName != value)
                {
                    OnContactLastNameChanging(value);
                    SendPropertyChanging();
                    _ContactLastName = value;
                    SendPropertyChanged("ContactLastName");
                    OnContactLastNameChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("ContactFirstName"), Required]
        public string ContactFirstName
        {
            get => _ContactFirstName;
            set
            {
                if (_ContactFirstName != value)
                {
                    OnContactFirstNameChanging(value);
                    SendPropertyChanging();
                    _ContactFirstName = value;
                    SendPropertyChanged("ContactFirstName");
                    OnContactFirstNameChanged();
                }
            }
        }

        [Column("Active"), Required]
        public bool? Active
        {
            get => _Active;
            set
            {
                if (_Active != value)
                {
                    OnActiveChanging(value);
                    SendPropertyChanging();
                    _Active = value;
                    SendPropertyChanged("Active");
                    OnActiveChanged();
                }
            }
        }

        [Column("AccountId")]
        public int? AccountId
        {
            get => _AccountId;
            set
            {
                if (_AccountId != value)
                {
                    OnAccountIdChanging(value);
                    SendPropertyChanging();
                    _AccountId = value;
                    SendPropertyChanged("AccountId");
                    OnAccountIdChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("CallbackSalt")]
        public string CallbackSalt
        {
            get => _CallbackSalt;
            set
            {
                if (_CallbackSalt != value)
                {
                    OnCallbackSaltChanging(value);
                    SendPropertyChanging();
                    _CallbackSalt = value;
                    SendPropertyChanged("CallbackSalt");
                    OnCallbackSaltChanged();
                }
            }
        }

        [Column("UserSpaceId")]
        public int? UserSpaceId
        {
            get => _UserSpaceId;
            set
            {
                if (_UserSpaceId != value)
                {
                    OnUserSpaceIdChanging(value);
                    SendPropertyChanging();
                    _UserSpaceId = value;
                    SendPropertyChanged("UserSpaceId");
                    OnUserSpaceIdChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("Login")]
        public string Login
        {
            get => _Login;
            set
            {
                if (_Login != value)
                {
                    OnLoginChanging(value);
                    SendPropertyChanging();
                    _Login = value;
                    SendPropertyChanged("Login");
                    OnLoginChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(1024), Column("Pwd")]
        public string Pwd
        {
            get => _Pwd;
            set
            {
                if (_Pwd != value)
                {
                    OnPwdChanging(value);
                    SendPropertyChanging();
                    _Pwd = value;
                    SendPropertyChanged("Pwd");
                    OnPwdChanged();
                }
            }
        }

        [Column("IsTechnicalAccount"), Required]
        public bool IsTechnicalAccount
        {
            get => _IsTechnicalAccount;
            set
            {
                if (_IsTechnicalAccount != value)
                {
                    OnIsTechnicalAccountChanging(value);
                    SendPropertyChanging();
                    _IsTechnicalAccount = value;
                    SendPropertyChanged("IsTechnicalAccount");
                    OnIsTechnicalAccountChanged();
                }
            }
        }

        [DataType(DataType.DateTime), Column("StatusDate")]
        public DateTime? StatusDate
        {
            get => _StatusDate;
            set
            {
                if (_StatusDate != value)
                {
                    OnStatusDateChanging(value);
                    SendPropertyChanging();
                    _StatusDate = value;
                    SendPropertyChanged("StatusDate");
                    OnStatusDateChanged();
                }
            }
        }

        [Column("BankStatusCode")]
        public int BankStatusCode
        {
            get => _BankStatusCode;
            set
            {
                if (_BankStatusCode != value)
                {
                    OnBankStatusCodeChanging(value);
                    SendPropertyChanging();
                    _BankStatusCode = value;
                    SendPropertyChanged("BankStatusCode");
                    OnBankStatusCodeChanged();
                }
            }
        }

        [DataType(DataType.Text), StringLength(255), Column("PivotalAccount")]
        public string PivotalAccount
        {
            get => _PivotalAccount;
            set
            {
                if (_PivotalAccount != value)
                {
                    OnPivotalAccountChanging(value);
                    SendPropertyChanging();
                    _PivotalAccount = value;
                    SendPropertyChanged("PivotalAccount");
                    OnPivotalAccountChanged();
                }
            }
        }

        public List<Resultat> Resultats { get; set; }

        public CompanyType CompanyType
        {
            get => _CompanyType;
            set
            {
                var previousValue = _CompanyType;
                if (previousValue != value)
                {
                    SendPropertyChanging();
                    _CompanyType = value;
                    if (value != null)
                    {
                        CompanyTypeId = value.CompanyTypeId;
                    }
                    else
                    {
                        _CompanyTypeId = default;
                    }
                    SendPropertyChanged("CompanyType");
                }
            }
        }

        public Country Country
        {
            get => _Country;
            set
            {
                var previousValue = _Country;
                if (previousValue != value)
                {
                    SendPropertyChanging();
                    _Country = value;
                    _CountryId = value?.CountryId ?? default;
                    SendPropertyChanged("Country");
                }
            }
        }

        [Column("IsKycIdSent"), Required]
        public bool IsKycIdSent
        {
            get => _IsKycIdSent;
            set
            {
                if (_IsKycIdSent != value)
                {
                    OnIsKycIdSentChanging(value);
                    SendPropertyChanging();
                    _IsKycIdSent = value;
                    SendPropertyChanged("IsKycIdSent");
                    OnIsKycIdSentChanged();
                }
            }
        }

        public event PropertyChangingEventHandler PropertyChanging;

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void SendPropertyChanging()
        {
            PropertyChanging?.Invoke(this, emptyChangingEventArgs);
        }

        protected virtual void SendPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void Attach_Resultats(Resultat entity)
        {
            SendPropertyChanging();
            entity.Company = this;
        }

        private void Detach_Resultats(Resultat entity)
        {
            SendPropertyChanging();
            entity.Company = null;
        }
    }

以及相关的表创建脚本:

create table T_Companies
(
    CompanyId            int identity (10) identity
        primary key nonclustered,
    CompanyName          varchar(1024) not null,
    CompanyTypeId        int           not null
        constraint FK_Company_CompanyType
            references T_CompanyTypes,
    CountryId            int           not null
        constraint FK_Company_Country
            references T_Countries,
    Active               bit           not null,
    AccountId            int,
    CallbackSalt         varchar(1024),
    UserSpaceId          int,
    Login                varchar(1024),
    Pwd                  varchar(1024),
    StatusDate           datetime(23, 3),
    BankStatusCode       int           not null,
    PivotalAccount       varchar(255),
    IsTechnicalAccount   bit           not null,
    CompanyStreetAddress varchar(256),
    CompanyCity          varchar(256),
    CompanyZipCode       varchar(10),
    CompanyVatNumber     varchar(30),
    ContactFirstName     varchar(20),
    ContactLastName      varchar(20),
    IsKycIdSent          bit           not null
)
go

[编辑 2]

对于完全相同的模型,这(在 nuget 引用的项目文件中)有效

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.8" />

而那些,不:

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.8" />
C# asp.net-core .net-core 实体框架核心

评论

11赞 DavidG 4/28/2019
您的 EF 模型可能与数据库中的内容不匹配,不幸的是,我们无法帮助您修复它,因为我们看不到这两个内容。可能是模型中标记为非 null 的内容,但数据库允许 null。
1赞 DavidG 4/28/2019
此外,如果您从调用中获得错误,那么您发布的代码的其余部分是完全多余的:)await DB.Companies.ToListAsync()
0赞 Natalie Perret 4/28/2019
@DavidG用于调试目的
0赞 Natalie Perret 4/28/2019
@DavidG,没有办法获得更好的跟踪或更准确的东西?:s
0赞 DavidG 4/28/2019
什么?您收到异常消息,跟踪对您无济于事。为我们提供 companies 表的实体和表定义。

答:

232赞 Ivan Stoev 4/28/2019 #1

更新

我之前所说的所有内容仍然适用,由于后来的 EF Core 可空性规则更改,只是有其他方法出错(最明显的是启用 NRT 的项目内的属性,这些属性现在默认被视为必需的,这与它们在非启用 NRT 的上下文中被视为完全相反)。string

我想在这里添加的是检测哪个列/属性导致问题的机制。

我有点忘记了哪个确切的 EF Core 版本添加了此类功能,但在最近的 EF Core 版本中,您可以使用 EnableDetailedErrors 方法打开详细错误日志记录,然后而不是 OP 异常(它仍然存在,但作为新的内部),您将收到类似于以下内容的消息InvalidOperationException

读取属性“{EntityName}”的数据库值时出错。{PropertyName}'。预期类型为“System.String”,但实际值为 null。

其中有问题的属性。{EntityName}.{PropertyName}


原文

错误消息指示 EF Core 正在尝试读取所需属性的值,即在数据库中不应具有值的属性,而是基础数据读取器在某些记录中报告该属性的值。stringnullnull

查看实体模型和相应的数据库表,可以看到许多属性 -> 列存在明显差异。、 、 、 、 - 所有这些都在模型中标记为,但在表中没有相应的约束。stringvarcharCompanyStreetAddressCompanyCityCompanyZipCodeCompanyVatNumberContactFirstNameContactLastName[Required]not null

因此,问题是由这些列中的一列或多列引起的。

您需要修复这种差异 - 可能是通过删除属性,因为现有数据中的约束已经被破坏。
如果使用的是 Database First 模型,则应在生成的 OnModelCreating 中删除,或者使用 EF Core Tools 重新生成模式。
[Required]builder.Property(x => x.MyProperty).IsRequired();

它在某些较旧的 EF Core 版本中“工作”这一事实并不重要 - 这是不正确的映射,因此应该修复。从技术上讲,它不应该从一开始就起作用。但请记住,EF Core 仍处于积极开发阶段,并且有许多 bug,这些 bug 将在下一个版本中修复。很可能在“工作”和“非工作”EF Core 版本之间进行了一些代码更改,从而修复了以前的错误行为。

评论

3赞 Natalie Perret 4/29/2019
谢谢,这其实是根本问题~~不知道EF Core在早期曾经比较“宽容”,以至于放弃了一些列约束。感谢您指出这一点。
9赞 Jota.Toledo 12/10/2020
就我而言,一旦我在项目级别激活了可为 null 的引用类型,而没有对实体类进行必要的更改,此错误就开始出现。禁用该功能成功了。
0赞 Lynn Crumbling 6/17/2023
感谢您回来并通过添加机制来更新它 - 超级有帮助。
0赞 Jurion 8/20/2023
谢谢!!!顺便说一句,使用编译器,我们只能在调试中添加它。(如果你正确地编码): #if DEBUG .EnableDetailedErrors() #endif
0赞 Darren M 11/4/2023
太有帮助了!今天早上,我开始在未创建的表上收到此错误,EnabledDetailsErrors为我指明了正确的方向。干杯!
63赞 Jogge 11/13/2019 #2

如果尝试从数据库中读取一些可为 null 的数据,但类型不可为 null,则可能会出现此错误。

如果在数据库中为 null,并且您有以下实体:MyInt

public class MyEntity
{
    public int Id { get; set; }
    public int MyInt { get; set; }
}

您将得到异常:System.Data.SqlTypes.SqlNullValueException: 'Data is Null. This method or property cannot be called on Null values.'

要解决此问题,只需将属性类型更改为 或 :MyIntNullable<int>int?

public class MyEntity
{
    public int Id { get; set; }
    public int? MyInt { get; set; }
}

注意:这不是对原始问题的回答,而是对标题中问题的回答。

评论

0赞 Jogge 5/26/2020
相关问题/答案:stackoverflow.com/q/62015584/7108481
2赞 DaveDev 5/18/2022
我喜欢你的“注意:”——这是客户要求的和他们实际想要的区别。
1赞 malthe.w 6/16/2023
“注意:这不是您想要/需要的答案,而是您提供给我们的 req 规范的答案。爱,IT”
0赞 Nelson Nyland 10/25/2023
有时你没有得到你想要的,但你得到了你需要的。:)
2赞 Hari Lakkakula 12/22/2019 #3
   public bool Isgstvailable { get; set; }

检查 SQL 视图或表中的位列。如果它返回 null ,则 C# 读取器无法读取并引发 null ref 异常。

商品及服务税(GST)的情况。Isgstvailable 为 null 然后强制转换(0 作为位) 否则消费税。Isgstvailable end 为 Isgstvailable

评论

0赞 Gert Arnold 12/24/2019
这似乎与问题完全无关。此外,如果是这样,这如何显着增加现有答案?
0赞 Hari Lakkakula 12/27/2019
谢谢@GertArnold,在实体框架中加载数据时,它与模型进行映射。如果有效负载数据与数据类型不匹配,则会引发异常。我有一个案例,我在数据库中有位字段,不幸的是它插入了空数据。加载位字段时,实体框架会抛出 null ref 异常,因为数据类型和加载的数据类型不匹配。
0赞 Gert Arnold 12/27/2019
是的,伊万已经充分解释了这一点。你的回答没有增加任何新内容。此外,它不是引发的 null 引用异常。
31赞 adospace 3/1/2020 #4

如果从 C# 8 启用最新的 Nullable 功能,也会出现此类异常。

EF Core,至少目前,它与 C# 8 可为 null 的类型不完全兼容。 因此,例如,假设您为项目启用了 Nullable 功能,如果您有如下类型:

public class MyEntity
{
   public string MyProperty { get; set; }
}

即使该属性使用 [Required] 属性标记,EF 核心也会引发此类异常,因为它要求数据库中的值不为 null(即,它不会使用 IsDbNull 测试列值)。

有关如何在 EF Core 中处理可为 null 的引用类型的详细信息,请查看: https://learn.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types

评论

7赞 Pascal R. 9/16/2020
简而言之:在 C# 8 中,MyProperty 需要字符串吗?如果它是数据库中可为 null 的值。
0赞 Madhav Shenoy 3/25/2022
我花了 2 个小时试图弄清楚 EF 失败的原因。谢谢
16赞 cryss 9/16/2020 #5

为了解决类似的异常问题,我必须明确地放置我的列映射。就我而言,我正在映射数据库视图。Data is NullIsRequired(false)

builder.Property(x => x.MyProperty).IsRequired(false);

评论

2赞 Dominic Shaw 11/12/2020
这样做表明,由于对我来说有问题的列是复合键的一部分,因此它被 EF 自动标记为必需,这导致了问题。这并没有解决问题,但它揭示了问题。TVM的
0赞 Smile4ever 2/16/2022
我必须将类型字符串更改为字符串吗?
9赞 Guillermo Perez 9/22/2020 #6

解决方案:是的,当模型将导致问题的字段标记为 [必需] 时,当(表的)列包含 NULL 时,会导致错误“SqlNullValueException:数据为 Null.”...使用数值字段可以轻松解决该问题,但是当字段为字符串类型时,问题真的很糟糕......

考虑以下 2 个使用配送路线示例的类,每个路由都有一个驱动程序,当然,每个驱动程序都有 1 个或多个路由。

public class Route
    {
        public int id { get; set; }       
        public string RouteName { get; set; }

        [Required] \\==> FIELD CAUSING THE PROBLEM
        public string UsuarioId { get; set; }

        public virtual Usuario Driver { get; set; }
}

public class Usuario
    {
        public string Id {get;set;
        public string Name { get; set; }                
        public virtual List<Route> Routes { get; set; } = new List<Route>();

    }

正如您可能猜到的那样,路由可以有一个驱动程序(或我称之为 Usuario),但一个驱动程序可以有多个路由,这形成了一对多关系,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder){            

     base.OnModelCreating(modelBuilder);

     modelBuilder.Entity<Usuario>()
        .HasMany<Route>(usuario => usuario.Routes)
        .WithOne(route => route.Driver)
        .HasForeignKey(route => route.UsuarioId)
        .OnDelete(DeleteBehavior.SetNull);
                
}

根据 FluentAPI,删除驱动程序时,行为是将 UsuarioId 字段(在路由模型中)设置为 NULL,但这违反了 [Required] 属性。因此,我们将无法删除“用户”(或“驱动程序”)表中的记录。此外,如果我们数据库中已经有数据,在本例中为 NULL UsuarioId 的路由,它将立即显示错误。

请记住,关键是:我们希望 [Required] 仅用于验证目的,因为我们可能拥有尚未分配给驱动程序 (UserId) 的路由,因此在数据库中,它应该被允许为 NULL,而不是在我们的 mvc 表单中。

若要解决此问题,请将该字段标记为 [必填],然后转到 DbContext 类,在该类中,您使用 Fluent API 定义了关系,并指定该列不是必需的,如下所示:

modelBuilder.Entity<Route>()
   .Property(p => p.UsuarioId).IsRequired(required: false);

因此,该字段现在在注释架构下是必需的,但最终将用于构建数据库的 Fluent API 不需要该字段。这将解决问题!

评论

0赞 Natalie Perret 9/23/2020
感谢您的回答,这绝对太棒了!
1赞 Daniel Genezini 10/27/2020 #7

不是 OP 情况,但这也可能与关系中的主键<>外键配置倒置有关。

例如:

entity
  .HasOne(e => e.Principal)
  .WithOne(e => e.Dependent)
  .HasForeignKey<Principal>(e => e.Key) <- This should be the dependent entity
  .HasPrincipalKey<Dependent>(e => e.Key); <- This should be the principal entity

而不是

entity
  .HasOne(e => e.Principal)
  .WithOne(e => e.Dependent)
  .HasForeignKey<Dependent>(e => e.Key)
  .HasPrincipalKey<Principal>(e => e.Key);
0赞 Asif Bin Zahir 3/17/2021 #8

只是想在这里发布这个;

这里的解决方案很棒,但在我的情况下不起作用。我使用的是 SQL 视图而不是表,并且我的字段在模型中没有标记 [Required]。

经过一些故障排除,我发现问题来自我的整数列为 null。我只是将模型中的 int 列更改为字符串(我需要此信息仅用于显示目的),它就成功了。

public int BatchId { get; set; }

public string BatchId { get; set; }

我希望这对某人有所帮助。感谢以上所有回答!

评论

1赞 shinyshark 11/29/2021
你好阿西夫,我有同样的问题。在我的情况下,最好从“int”更改为“int?”以允许 null。数据库中的相应列也允许 null 值。它之所以对你有用,是因为字符串总是可以为空的。
0赞 BedfordNYGuy 6/11/2023
我更改了我所有的观点 int -> int?并将 HasNoKey 和我的所有字符串设置为 .IsRequired(假);我仍然得到 SqlNullValueException。我可以设置一些全局标志吗?顺便说一句,所有行/列都有有效数据。所以我没有空值/
1赞 Kannagi Lee 2/16/2022 #9

[使用 isRequired()][1] 我通过在数据库上下文中定义表的所有属性(由 scafford 生成)来解决我的问题,无论是否需要。

2赞 Ali Raji 6/27/2022 #10

从模型中删除 [必需]。 并使用: < cshtml 中的输入 data-val=“true” data-val-required=“write a message for validation” >

6赞 skillworks 7/9/2022 #11

如果要忽略这些值,则添加 DefaultIfEmpty() 有效。

_context.<YourDbSet>.DefaultIfEmpty().ToListAsync();

在这种情况下:

var companyEditVMs = await DB.Companies
    .OrderBy(company => company.CompanyId == 1 
        ? "_" + company.CompanyName 
        : company.CompanyName
    )
    Select(a => new CompanyEditVM(..--..)).DefaultIfEmpty()
    .ToListAsync();

评论

0赞 Shahid Iqbal 2/9/2023
是的,这是我自己加入所有这些表的问题。谢谢@skillworks节省了我的时间。
5赞 bobt 7/22/2022 #12

就我而言,这是由于我将数据库中的列从不可空更改为可空,然后忘记了我需要再次重新运行 Scaffold-DbContext 以便更新实体类。我正在使用数据库优先的 Entity Framework Core。

1赞 Muflix 6/8/2023 #13

我通过添加

modelBuilder.Entity<EntityName>().HasNoKey();

to 方法DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder)

因为我的存储过程为属性返回。nullId

1赞 Sanjay 7/19/2023 #14

我只需要在模型上放置 (int?) 的 c# 属性并且工作正常,因为数据库列允许 null。

评论

1赞 Community 7/23/2023
正如目前所写的那样,你的答案尚不清楚。请编辑以添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以在帮助中心找到有关如何写出好答案的更多信息。
1赞 Chris Go 8/29/2023 #15

我在视图上遇到了同样的问题。SQL/SSMS 的最大问题是视图不会刷新,因此 EF 基架不会获取更改。

此代码将刷新视图元数据,使 EF 能够在基架时查看 NULL/NOT NULL 属性更改等小更改。

-- Loop and refresh all views.
DECLARE @ViewName VARCHAR(100), @SchemaName VARCHAR(20);

DECLARE [views_cursor] CURSOR FOR 
SELECT v.[name] AS ViewName, s.[name] AS SchemaName 
FROM [sys].[views] v INNER JOIN [sys].[schemas] s ON s.[schema_id] = v.[schema_id]
WHERE v.[type] = 'V'
ORDER BY SchemaName, ViewName;

OPEN [views_cursor];

FETCH NEXT FROM [views_cursor] 
INTO @ViewName, @SchemaName;

-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        DECLARE @FullName VARCHAR(120) = @SchemaName + '.' + @ViewName;
        PRINT 'Refreshing: ' + @FullName
        EXEC sp_refreshview @FullName
    END TRY
    BEGIN CATCH
        PRINT 'Error: ' + @FullName
    END CATCH
    FETCH NEXT FROM [views_cursor] 
    INTO @ViewName, @SchemaName;
END

CLOSE [views_cursor];
DEALLOCATE [views_cursor];
GO
1赞 Ricky Gummadi 10/6/2023 #16

我知道这是一个老问题,但以防万一有人还在看。从

public string RRN { get; set; }

public string? RRN { get; set; }

或者在 cproj 文件中禁用可为 null 的

 <Nullable>disable</Nullable>