Eho*_*ret 3 c# entity-framework-core .net-core asp.net-core
我在ASP.NET Core应用程序和Controller动作中使用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);
}
Run Code Online (Sandbox Code Playgroud)
痕迹
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()
Run Code Online (Sandbox Code Playgroud)
我什至试着做var companies = await DB.Companies.ToListAsync()。和我有完全一样的例外。
也许我希望能够获取由EF Core执行的查询以手动执行,以便我可以尝试找出查询出了什么问题。
我想知道可能会发生什么。特别是由于仍然可以从数据库中获取其他实体,例如用户或国家/地区。
知道如何解决实际的潜在问题吗?
[编辑]
在“代码”中唯一实际更改的是nuget引用,我基本上升级了几乎所有内容,尽管它并没有破坏代码中的引用,似乎它改变了EF Core以某种方式(疯狂猜测)解释数据库的方式。
我确实在nuget软件包更新发生并且工作正常之前将git存储库重置为该点。然后,我决定只是将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 PropertyChangedEventArg
Jog*_*gge 30
如果您尝试从数据库读取一些可为空的数据,但您的类型不可为空,则可能会出现此错误。
如果MyInt在数据库中可以为空并且您有这个实体:
public class MyEntity
{
public int Id { get; set; }
public int MyInt { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
你会得到异常: System.Data.SqlTypes.SqlNullValueException: 'Data is Null. This method or property cannot be called on Null values.'
要解决此问题,只需将您的MyInt属性类型更改为Nullable<int>或int?:
public class MyEntity
{
public int Id { get; set; }
public int? MyInt { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
注意:这不是对原始问题的回答,而是对标题中问题的回答。
如果从 C# 8 启用最新的 Nullable 功能,也会出现这种异常。
EF Core 至少目前与 C# 8 可空类型不完全兼容。例如,假设您为项目启用了 Nullable 功能,如果您有这样的类型:
public class MyEntity
{
public string MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
即使它没有用 [Required] 属性标记的属性,EF 核心也会引发这种异常,因为它要求数据库中的值不为空(即它不使用 IsDbNull 测试列值)。
有关如何在 EF 核心中处理可为空引用类型的更多信息,请查看:https : //docs.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types
解决方案:是的,错误“SqlNullValueException:数据为空”。当模型将导致问题的字段标记为 [Required] 时,(表的)列包含 NULL 时会导致问题...使用数字字段很容易解决问题,但当字段为字符串类型时,问题确实很糟糕。 。
想想下面两个使用分发路线示例的类,每条路线都有一个司机,当然,每个司机都有 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>();
}Run Code Online (Sandbox Code Playgroud)
正如您可能猜到的,一条路线可以有一个驱动程序(或我所说的 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);
}Run Code Online (Sandbox Code Playgroud)
根据 FluentAPI,当删除驱动程序时,行为是将 UsuarioId 字段(在路由模型中)设置为 NULL,但这违反了 [Required] 属性。因此我们将无法删除用户(或驱动程序)表中的记录。另外,如果数据库中已有数据,在本例中,UsuarioId 为 NULL 的路由,它将立即显示错误。
请记住,要点是:我们希望 [Required] 仅用于验证目的,因为我们可能拥有尚未分配给驱动程序(UserId)的路由,因此在数据库中,应允许它为 NULL ,而不是我们的 mvc 形式。
要解决此问题,请将该字段标记为 [required],然后转到使用 Fluent API 定义关系的 DbContext 类,并指定该列不是必需的,如下所示:
modelBuilder.Entity<Route>()
.Property(p => p.UsuarioId).IsRequired(required: false);Run Code Online (Sandbox Code Playgroud)
因此,该字段现在在注释模式下是必需的,但最终用于构建数据库的 Fluent API 不需要。这将解决问题!
错误消息表明EF Core正在尝试读取所需属性的string值,即,该属性在数据库中永远不应该具有值,而是基础数据读取器在某些记录中报告该属性的值。nullnull
查看您的实体模型和相应的数据库表,您可以看到许多string属性-> varchar列之间明显的差异。CompanyStreetAddress,CompanyCity,CompanyZipCode,CompanyVatNumber,ContactFirstName,ContactLastName-所有这些都被标记为[Required]模型,位没有相应的not null表约束。
因此,问题是由这些列中的一个或多个引起的。
您需要解决该差异-可能是通过删除[Required]属性,因为约束已在现有数据中打破。
它在某些较旧的EF Core版本中“起作用”的事实无关紧要-这是错误的映射,因此应予以修复。从技术上讲,它不应该从一开始就起作用。但是请记住,EF Core仍在积极开发中,并且有许多错误已在下一版本中修复。很有可能在“正常”和“无效” EF Core版本之间进行了一些代码更改,从而修复了以前的错误行为。
如果您想忽略这些值,可以添加 DefaultIfEmpty() 。
_context.<YourDbSet>.DefaultIfEmpty().ToListAsync();
Run Code Online (Sandbox Code Playgroud)
在这种情况下:
var companyEditVMs = await DB.Companies
.OrderBy(company => company.CompanyId == 1
? "_" + company.CompanyName
: company.CompanyName
)
Select(a => new CompanyEditVM(..--..)).DefaultIfEmpty()
.ToListAsync();
Run Code Online (Sandbox Code Playgroud)
为了解决类似的Data is Null异常问题,我必须明确地放置IsRequired(false)我的列映射。就我而言,我正在映射数据库视图。
builder.Property(x => x.MyProperty).IsRequired(false);
Run Code Online (Sandbox Code Playgroud)
就我而言,这是因为我将数据库中的列从不可为空更改为可空,然后忘记了我需要再次重新运行 Scaffold-DbContext 以便更新实体类。我正在使用数据库优先的 Entity Framework Core。
| 归档时间: |
|
| 查看次数: |
3372 次 |
| 最近记录: |