Во-первых, я бы, вероятно, все еще считал себя новичком в 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 в обоих проектах, и они одинаковы.
Так, как я могу найти, в чем проблема?