将EF 6 WPF应用程序转换为EF Core,从正在运行的查询中获取空异常

时间:2019-04-08 09:05:33

标签: c# wpf entity-framework entity-framework-core

首先,我可能仍会将自己列为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.TypedProjectionShaper 3.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.QueryingEnumerable 1.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导航,Func 2 resultCollectionFactory, MaterializedAnonymousObject& outerKey, Boolean tracking, Func 1 relatededCollectionFactory,Func 3 correlationPredicate) at lambda_method(Closure , ValueBuffer ) at System.Linq.Enumerable.SelectEnumerableIterator 2.MoveNext()      在Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor 1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List 1..ctor(IEnumerable 1 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子属性,查询也可以正常工作。我已经检查了两个项目中脚手架生成的代码,它们是相同的。

那我怎么找到问题所在?

1 个答案:

答案 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