Преобразовал приложение EF 6 WPF в EF Core, получив нулевое исключение из того, что было рабочим запросом - PullRequest
0 голосов
/ 08 апреля 2019

Во-первых, я бы, вероятно, все еще считал себя новичком в EF. Выполнены некоторые кодовые первые миграции, но только простые вещи.

В любом случае, у меня есть приложение WPF, которое я создал, использующее EF 6. Сейчас я изучаю .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: 'Значение не может быть нулевым. Имя параметра: источник '

Трассировка стека

в 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 операция, Func 3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable 1.Enumerator.MoveNext () в Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.CorrelateSubquery [TInner, TOut, TCollection] (Int32 correlatedCollectionId, навигация INavigation, Func 2 resultCollectionFactory, MaterializedAnonymousObject& outerKey, Boolean tracking, Func 1 correlatedCollectionFactory, 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) в EPQT.ServiceLayer.TesterService.GetTestData (DateTime startDate, DateTime endDate, String testerId, String productFilter) в C: \ Visual Studio 2017 \ Projects \ Extractor \ Core \ EPQT.ServiceLayer \ TesterService.cs: строка 120 в EPQT.Modules.TesterQuery.Views.TestQueryViewModel. <> c__DisplayClass54_0.b__0 () в C: \ Visual Studio 2017 \ Projects \ Extractor \ Modules \ EPQT.Modules.TesterQuery \ Views \ TestQueryViewModel.cs: строка 218 в System.Threading.Tasks.Task.InnerInvoke () в System.Threading.Tasks.Task. <> c. <. cctor> b__277_0 (объектный объект) в System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop (Thread threadPoolThread, ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта)

Итак, я сузил вопрос до этой строки.

UpperLimit = y.StepNumericlimit1.FirstOrDefault().StepNumericlimit2.FirstOrDefault().HighLimit.ToString(),

Таким образом, y потенциально имеет много детей, называемых StepNumericlimit1, и у которых потенциально есть много детей, называемых StepNumericlimit2.

По сути, я пытаюсь сказать, если у y есть StepNumericlimit1 детей, тогда возьмите первого. Затем, если найден ребенок, проверьте, есть ли у него StepNumericlimit2 детей. Если это так, то получите свойство Data от первого потомка.

Не уверен, что ядро ​​EF справляется с этим, или как он сгенерировал код, или, может быть, даже мой запрос написан плохо ... или, может быть, все вышеперечисленное lol

ОБНОВЛЕНИЕ: Некоторый код, сгенерированный 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. Я проверил сгенерированный код из scafolding в обоих проектах, и они одинаковы.

Так, как я могу найти, в чем проблема?

1 Ответ

1 голос
/ 08 апреля 2019

Это решение должно работать нормально !!

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...