首先,我可能仍会将自己列为EF的新手。先完成一些代码迁移,但仅完成简单的事情。
无论如何,我有一个使用EF 6制作的WPF应用程序。我现在正在研究.Net Core 3,并决定着手转换该应用程序。
生成我使用脚手架的数据库模型。
好吧,这个问题。 在当前运行EF6的应用中,此代码可以正常工作。
var items2 = DbContext.UutResult.Where(x =>
x.StartDateTime != null && (x.StartDateTime.Value.Date >= startDate &&
x.StartDateTime.Value.Date <= endDate &&
x.StationId == testerId)).Select(x => new TestResultItem()
{
TesterId = (int) x.TestSocketIndex,
TesterType = x.StationId,
TestDateTime = (DateTime) x.StartDateTime,
TestResult = x.UutStatus,
PanelBarcode = x.BatchSerialNumber,
UutBarcode = x.UutStatus,
TestTimeSec = (double) x.ExecutionTime,
TestSteps = x.StepResult.Where(y => y.StepGroup == "Main").Select(y => new TestResultStepItem()
{
StepName = y.StepName,
Report = y.ReportText,
TestResult = y.Status,
UpperLimit = y.StepNumericlimit1.FirstOrDefault().StepNumericlimit2.FirstOrDefault().HighLimit.ToString(),
OrderId = (int)y.OrderNumber
}).ToList()
}).ToList();
但是在EF内核中运行相同的代码时,会出现以下错误。
System.ArgumentNullException:'值不能为null。参数名称: 来源”
堆栈跟踪
在System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument参数) 在System.Linq.Enumerable.TryGetFirst [TSource](IEnumerable
1 source, Boolean& found) at lambda_method(Closure , QueryContext , TransparentIdentifier
2) 在Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer) at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper
3.Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.IShaper.Shape(QueryContext queryContext,ValueBuffer&valueBuffer) 在Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func
3操作中,函数3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable
1.Enumerator.MoveNext() 在Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.CorrelateSubquery [TInner,TOut,TCollection](Int32 relatededCollectionId,Inavigation导航,Func2 resultCollectionFactory, MaterializedAnonymousObject& outerKey, Boolean tracking, Func
1 relatededCollectionFactory,Func3 correlationPredicate) at lambda_method(Closure , ValueBuffer ) at System.Linq.Enumerable.SelectEnumerableIterator
2.MoveNext() 在Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1源)处获得 在C:\ Visual Studio 2017 \ Projects \ Extractor \ Core \ EPQT.ServiceLayer \ TesterService.cs:line 120中的EPQT.ServiceLayer.TesterService.GetTestData(DateTime startDate,DateTime endDate,String testerId,String productFilter) 在C:\ Visual Studio 2017 \ Projects \ Extractor \ Modules \ EPQT.Modules.TesterQuery \ Views \ TestQueryViewModel.cs:line 218中的EPQT.Modules.TesterQuery.Views.TestQueryViewModel。<> c__DisplayClass54_0.b__0() 在System.Threading.Tasks.Task.InnerInvoke() 在System.Threading.Tasks.Task。<> c。<。cctor> b__277_0(Object obj) 在System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(线程threadPoolThread,ExecutionContext executeContext,ContextCallback回调,对象状态)处
所以我将问题缩小到这一行。
UpperLimit = y.StepNumericlimit1.FirstOrDefault().StepNumericlimit2.FirstOrDefault().HighLimit.ToString(),
因此,y
可能有很多孩子,称为StepNumericlimit1
,而潜在地有很多孩子,称为StepNumericlimit2
。
基本上,我想说的是y
是否有StepNumericlimit1
个孩子,然后抓住第一个孩子。然后,如果找到一个孩子,请检查该孩子是否有StepNumericlimit2
个孩子。如果是这样,则从第一个孩子那里抢夺属性Data
。
不确定是EF内核是如何处理它的,还是它生成代码的方式,或者甚至我的查询它编写得很差……还是以上所有这些笑话
更新:某些EF生成的代码,删除了不相关的代码。
public partial class StepResult
{
public StepResult()
{
StepNumericlimit1 = new HashSet<StepNumericlimit1>();
}
public Guid Id { get; set; }
public Guid? UutResult { get; set; }
public virtual UutResult UutResultNavigation { get; set; }
public virtual ICollection<StepNumericlimit1> StepNumericlimit1 { get; set; }
}
public partial class StepNumericlimit1
{
public StepNumericlimit1()
{
StepNumericlimit2 = new HashSet<StepNumericlimit2>();
}
public Guid Id { get; set; }
public Guid? StepResult { get; set; }
public double? Data { get; set; }
public virtual StepResult StepResultNavigation { get; set; }
public virtual ICollection<StepNumericlimit2> StepNumericlimit2 { get; set; }
}
public partial class StepNumericlimit2
{
public Guid? PropResult { get; set; }
public double? HighLimit { get; set; }
public double? LowLimit { get; set; }
public virtual StepNumericlimit1 PropResultNavigation { get; set; }
}
OnModelCreating
modelBuilder.Entity<StepNumericlimit1>(entity =>
{
entity.ToTable("STEP_NUMERICLIMIT1");
entity.HasIndex(e => e.StepResult)
.HasName("StepResultIndex");
entity.Property(e => e.StepResult).HasColumnName("STEP_RESULT");
entity.HasOne(d => d.StepResultNavigation)
.WithMany(p => p.StepNumericlimit1)
.HasForeignKey(d => d.StepResult)
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("STEP_NUMERICLIMIT1_STEP_RESULT_FK");
});
modelBuilder.Entity<StepNumericlimit2>(entity =>
{
entity.ToTable("STEP_NUMERICLIMIT2");
entity.Property(e => e.HighLimit).HasColumnName("HIGH_LIMIT");
entity.Property(e => e.LowLimit).HasColumnName("LOW_LIMIT");
entity.HasOne(d => d.PropResultNavigation)
.WithMany(p => p.StepNumericlimit2)
.HasForeignKey(d => d.PropResult)
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("STEP_NUMERICLIMIT2_STEP_NUMERICLIMIT1_FK");
});
更新2: 因此,为了提供更多信息,我旨在创建一个包含虚拟数据的新项目和数据库,但非常重要的一点,即删除不需要的表和与查询无关的列。
我这样做了,现在即使使用NULL子属性,查询也可以正常工作。我已经检查了两个项目中脚手架生成的代码,它们是相同的。
那我怎么找到问题所在?
答案 0 :(得分:1)
此解决方案应该可以正常工作!
var items2 = DbContext.UutResult.Include(r=>r.StepNumericlimit1).ThenInclude(r=>r.StepNumericlimit2).Where(x =>
x.StartDateTime != null && (x.StartDateTime.Value.Date >= startDate &&
x.StartDateTime.Value.Date <= endDate &&
x.StationId == testerId)).Select(x => new TestResultItem()
{
TesterId = (int) x.TestSocketIndex,
TesterType = x.StationId,
TestDateTime = (DateTime) x.StartDateTime,
TestResult = x.UutStatus,
PanelBarcode = x.BatchSerialNumber,
UutBarcode = x.UutStatus,
TestTimeSec = (double) x.ExecutionTime,
TestSteps = x.StepResult.Where(y => y.StepGroup == "Main").Select(y => new TestResultStepItem()
{
StepName = y.StepName,
Report = y.ReportText,
TestResult = y.Status,
UpperLimit = y.StepNumericlimit1.FirstOrDefault().StepNumericlimit2.FirstOrDefault().HighLimit.ToString(),
OrderId = (int)y.OrderNumber
}).ToList()
}).ToList();
有关更多信息,我邀请您阅读本文档。
https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/read-related-data?view=aspnetcore-2.2