Efcore: NullReferenceException when executing simple query

Created on 17 Dec 2015  路  14Comments  路  Source: dotnet/efcore

I'm using RC1, and I have a DbContext that I'm executing a simple query on, and a null exception is being thrown deep into the EF stack. The query is:

context.Clients.FirstOrDefault(c => c.Code == "test");

The exception is:

System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=Anonymously Hosted DynamicMethods Assembly

And the stack track is:

       at lambda_method(Closure , ValueBuffer )
       at Microsoft.Data.Entity.Query.EntityLoadInfo.Materialize()
       at Microsoft.Data.Entity.Query.Internal.QueryBuffer.GetEntity(IKeyValue keyValue, EntityLoadInfo entityLoadInfo, Boolean queryStateManager)
       at Microsoft.Data.Entity.Query.ExpressionVisitors.RelationalEntityQueryableExpressionVisitor.CreateEntity[TEntity](IQuerySource querySource, ValueBuffer valueBuffer, Int32 valueBufferOffset, QueryContext queryContext, IEntityType entityType, Boolean trackingQuery, KeyValueFactory keyValueFactory, Func`2 materializer, Boolean allowNullResult, Boolean useQueryBuffer)
       at lambda_method(Closure , ValueBuffer )
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
       at lambda_method(Closure , QueryContext )
       at Microsoft.Data.Entity.Query.Internal.QueryCompiler.<>c__DisplayClass18_1`1.<CompileQuery>b__1(QueryContext qc)
       at Microsoft.Data.Entity.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
       at Microsoft.Data.Entity.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
       at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)

....

       at Microsoft.Extensions.DependencyInjection.ServiceLookup.FactoryService.Invoke(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite.Invoke(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite.Invoke(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceProvider.ScopedCallSite.Invoke(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceProvider.<>c__DisplayClass12_0.<RealizeService>b__0(ServiceProvider provider)
       at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)

....

       at Microsoft.AspNet.Mvc.Filters.ActionFilterAttribute.<OnActionExecutionAsync>d__6.MoveNext()

Most helpful comment

Actually, I just figured it out. It was #5 in the above list.
The DateTime property is non-nullable, but is represented as a nullable smalldate with a default value in the database. The row I was trying to read had a null value. I guess it couldn't fit the null database value into the non-nullable property.

This was working in EF5, so not sure if you'd consider this a bug or not.

All 14 comments

If it helps at all, if I access just a single property of the entity, that works as expected.

context.Clients.Where(c => c.Code == "test").Select(c => c.Code).FirstOrDefault();

@joshmouch can you share your model (entity classes and context) to help us reproduce this issue.

I'm guessing the exception happens when it is trying to materialize one particular property of your entity

That was my guess, as well. Is there a way I can share it with you privately?

So there are a few things with this entity:

  1. It implements an interface.
  2. It has a DataContract attribute.
  3. One property is a nullable enum of type byte (not int).
  4. It has one read-only property (setter is private).
  5. It has a DateTime property configured with .ValueGeneratedOnAdd().
  6. The table name and SQL property names are all manually configured.

Actually, I just figured it out. It was #5 in the above list.
The DateTime property is non-nullable, but is represented as a nullable smalldate with a default value in the database. The row I was trying to read had a null value. I guess it couldn't fit the null database value into the non-nullable property.

This was working in EF5, so not sure if you'd consider this a bug or not.

@joshmouch I would expect the same situation to cause an exception in EF5, although likely with a more informative message. Is that what you mean when you said this was working in EF5 or am I missing some other detail?

You could be right. I'm looking through the EF5 code and database, and I can't say with confidence that this didn't throw an exception.

So maybe the bug is just give a better error message?

@joshmouch are you mapping to an existing database? If I use EF to create the database then the column is created as non-nullable.

Model

``` c#
class TestContext : DbContext
{
public DbSet Blogs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Sample;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Created)
            .ValueGeneratedOnAdd()
            .HasDefaultValueSql("GETDATE()");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public DateTime Created { get; set; }
}
Generated schema

``` SQL
CREATE TABLE [Blog] (
    [BlogId] int NOT NULL IDENTITY,
    [Created] datetime2 NOT NULL DEFAULT (GETDATE()),
    [Url] nvarchar(max),
    CONSTRAINT [PK_Blog] PRIMARY KEY ([BlogId])
);

Yes, this is an existing database. So the code first model and the database schema aren't in sync. I think the problem is just with the error message making it difficult to determine the reason for the error.

@joshmouch thanks for confirming. We will discuss on our end... this is a very perf-sensitive area of the stack, so we need to be very careful about adding logic to handle negative cases.

@joshmouch opened #4289 to look at the overall story of better errors in query (in a way that does not adversely affect performance)

@rowanmiller Thanks. My case is an outside one, so probably not high priority.

Was this page helpful?
0 / 5 - 0 ratings