Base solution for your next web application
Open Closed

NullReferenceException with tests when using include #4029


User avatar
0
DennisAhlin created

I get null reference exception when trying to include children in tests and I cannot figure out why? Error:

System.NullReferenceException : Object reference not set to an instance of an object.
   at lambda_method(Closure , AnonymousObject )
   at System.Linq.Lookup`2.CreateForJoin(IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.<JoinIterator>d__37`4.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryBuffer.IncludeCollection(Int32 includeId, INavigation navigation, INavigation inverseNavigation, IEntityType targetEntityType, IClrCollectionAccessor clrCollectionAccessor, IClrPropertySetter inverseClrPropertySetter, Boolean tracking, Object entity, Func`1 relatedEntitiesFactory)
   at lambda_method(Closure , QueryContext , Parent , Object[] )
   at Microsoft.EntityFrameworkCore.Query.Internal.IncludeCompiler._Include[TEntity](QueryContext queryContext, TEntity entity, Object[] included, Action`3 fixup)
   at lambda_method(Closure , Parent )
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at lambda_method(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass17_0`1.&lt;CompileQueryCore&gt;b__0(QueryContext qc)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.Single[TSource](IQueryable`1 source, Expression`1 predicate)......

If I remove IMustHaveTenant from Child, the code works? My classes:

public class Parent : FullAuditedEntity
{
    public virtual ICollection&lt;Child&gt; Children { get; set; }
}

public class Child : FullAuditedEntity, IMustHaveTenant
{
    [Required]
    public int TenantId { get; set; }

    [ForeignKey("ParentId")]
    public virtual Parent Parent { get; set; }
    [Required]
    public virtual int ParentId { get; set; }
}

The test (that throws the exception):

var parentId = 1;
var tenantId = GetCurrentTenant().Id;

//Arrange
UsingDbContext(ctx =>
{
    ctx.Parents.Add(new Parent
    {
        Id = parentId
    });
                
    ctx.Children.Add(new Child
    {
        TenantId = tenantId,
        ParentId = parentId
    });
});

//Act
//I want to test stuff here that should change parent and/or children
            
//Assert
var parent = UsingDbContext(ctx =>
{
    return ctx.Parents.Include(p => p.Children).Single(i => i.Id == parentId); //Exception thrown here
});

parent.Id.ShouldBe(1);

parent.Children.Count.ShouldBe(1);
parent.Children.First().ParentId.ShouldBe(parentId);
parent.Children.First().TenantId.ShouldBe(tenantId);

5 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    This problem might be related to EF Core, have you checked it's repository ? By the way, why do you put MustHaveTenant to child object ?

  • User Avatar
    0
    DennisAhlin created

    After plenty of Googling and checking their issues I have not found anything that can help me.

    The child have IMustHaveTenant because two different tenants should be able to see the Parent, but they should only see the Children they have created. Maybe there is another way of solving this?

    Is there any way of logging the SQL from the query?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @DennisAhlin,

    I also googled it and checked EF Core's github repo, but I couldn't find any related issue. There is one issue but I couldn't be sure if it is related to your problem or not, so I didn't post it here.

    Instead of include, you can use EnsureCollectionLoadedAsync extension method. You need to define a repository to use this extension method.

  • User Avatar
    0
    DennisAhlin created

    Is there any way of logging the SQL from the query?

    Yes, I can use EnsureCollectionLoaded in this example where I use single. However if I want to select multiple parents I have to do like this? Which I assume is terrible performance wise?

    var query = _parentsRepository
        .GetAll()
        .Where(p => *somePredicate*)
        .ToArray();
    
    foreach (var parent in parents)
    {
        await _parentsRepository.EnsureCollectionLoadedAsync(parent, p => p.Children);
    }
    
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Is there any way of logging the SQL from the query?

    I don't know if it is possible, you can check EF Core's repository for that.

    By the way, is this happening only for test project ?