0

First off, I would probably still class myself as a novice in EF. Done some code first migrations but only simple things.

Anyway, I have a WPF app I made which is using EF 6. I am now having a look at .Net Core 3 and decided to have a go at converting the app.

Generating the database models I used scaffolding.

Ok so the problem. In the current app running EF6 this code works fine.

            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();

But running the same in EF core I get the following error.

System.ArgumentNullException: 'Value cannot be null. Parameter name: source'

Stack Trace

at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument) at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable1 source, Boolean& found) at lambda_method(Closure , QueryContext , TransparentIdentifier2 ) at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper3.Shape(QueryContext queryContext, ValueBuffer& valueBuffer) at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ProjectionShaper.TypedProjectionShaper3.Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.IShaper.Shape(QueryContext queryContext, ValueBuffer& valueBuffer) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func3 operation, Func3 verifySucceeded) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.Enumerator.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.CorrelateSubquery[TInner,TOut,TCollection](Int32 correlatedCollectionId, INavigation navigation, Func2 resultCollectionFactory, MaterializedAnonymousObject& outerKey, Boolean tracking, Func1 correlatedCollectionFactory, Func3 correlationPredicate) at lambda_method(Closure , ValueBuffer ) at System.Linq.Enumerable.SelectEnumerableIterator2.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor1.EnumeratorExceptionInterceptor.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at EPQT.ServiceLayer.TesterService.GetTestData(DateTime startDate, DateTime endDate, String testerId, String productFilter) in C:\Visual Studio 2017\Projects\Extractor\Core\EPQT.ServiceLayer\TesterService.cs:line 120 at EPQT.Modules.TesterQuery.Views.TestQueryViewModel.<>c__DisplayClass54_0.b__0() in C:\Visual Studio 2017\Projects\Extractor\Modules\EPQT.Modules.TesterQuery\Views\TestQueryViewModel.cs:line 218 at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.<>c.<.cctor>b__277_0(Object obj) at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)

So I narrowed down the issue to this line.

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

So y potentially has many children called StepNumericlimit1 and that potentially has many children called StepNumericlimit2.

Basically I am trying to say if y has any StepNumericlimit1 children then grab the first one. Then, if there is a child found, check to see if that has any StepNumericlimit2 children. If it does, then grab the property Data from the first child.

Not sure if it's how EF core handles this or the way it has genereated the code or maybe even my query it written poorly... or maybe all the above lol

UPDATE: Some EF generated code, deleted irrelevant code.

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");
        });

UPDATE 2: So in order to provide more information I was aiming to create a new project and database with dummy data, but very minamal i.e. stripping out tables not required and columns not related to the query.

I did this and now the query works fine, even with NULL child properties. I have checked the generated code from scafolding in both projects and they are the same.

So how can I find what the issue is?

Gaz83
  • 2,293
  • 4
  • 32
  • 57
  • Check your connection string, might be that it is not defined or not properly and in addition, have a look at some of these answers and see if one can help=> https://stackoverflow.com/questions/16281133/value-cannot-be-null-parameter-name-source – Dimitri Apr 08 '19 at 09:08
  • 1
    I know its not the string because I can run other less complicated querys fine. Plus, if i comment out that one line I identified as the issue, it runs fine aswell. – Gaz83 Apr 08 '19 at 09:09
  • Editted, have a look at the url, check your object y and its (referenced)properties to see if any of them are NULL. – Dimitri Apr 08 '19 at 09:11
  • 2
    In Ef core you need to use Include() function to retrieve related data ( children ) before where() function DbContext.UutResult.Include(... ) – Alaaeddine HFIDHI Apr 08 '19 at 09:12
  • I already had a look at that link. Didn't really help. I am assuming property is NULL because of the error. Question is how do i handle this? EF 6 did this for me, i assume as it didn't give me the exception. – Gaz83 Apr 08 '19 at 09:15
  • @AlaaeddineHFIDHI oh really? ok I will try this now, thank you. – Gaz83 Apr 08 '19 at 09:16
  • @AlaaeddineHFIDHI is right, EF Core (opposed to EF 6) does not load related objects automatically (no lazy-loading) – vasily.sib Apr 08 '19 at 09:16
  • 1
    There is [many other things that works different](https://learn.microsoft.com/en-us/ef/efcore-and-ef6/) in EF 6 and EF Core – vasily.sib Apr 08 '19 at 09:19

1 Answers1

1

This solution should be work fine !!

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();

For more informations, I invite you to read this documentation
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/read-related-data?view=aspnetcore-2.2

  • doesn't seem to work. I took your query, modified the top line to read line this. "DbContext.UutResult.Include(x => x.StepResult).ThenInclude(x => x.StepNumericlimit1).ThenInclude(x => x.StepNumericlimit2).Where(" But still the error. – Gaz83 Apr 08 '19 at 09:26
  • can you give me the database schema ? – Alaaeddine HFIDHI Apr 08 '19 at 09:30
  • It's a business database so I am limited to what I can provide. Whats is it you are looking for and I might be able to help. – Gaz83 Apr 08 '19 at 09:39
  • i Need to see the realtion between concerned tables to be able to resolve this issue – Alaaeddine HFIDHI Apr 08 '19 at 09:45
  • I will add some EF generated code, stripping out none esstentiall properties. – Gaz83 Apr 08 '19 at 09:48