dotnet / dotnet/efcore

NullReferenceException getting navigational property just set (using lazy loading)

Open
#33,055 3 comments 0 reactions 0 assignees View on GitHub
area-change-tracking consider-for-next-release customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

In the following code a product is created, then an orderline for that product is created.

On line 39 (marked with /\*39\*/) line.Product is set with a non-null value.
On line 40, the line.Product is dereferrenced and results in a NullReferenceException.
This should not be the case. "line.Product" should not be null at this stage.

The project uses an SQLite in-memory database with lazy loading and change tracking proxies.

```
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public static class Program
{
static OrderContext Context = new OrderContext();
static int prod1Id;

public static void Main(string[] args)
{
Context.Database.EnsureDeleted();
Context.Database.EnsureCreated();

CreateProduct();
AddOrderline();
}

public static void CreateProduct()
{
// Create and store a product with Id=1:
var prod = Context.Products.CreateProxy();
prod.Name = "FooBar";
prod.CatalogPrice = 12.99m;
Context.Products.Add(prod);
Context.SaveChanges();
prod1Id = prod.Id;
Console.WriteLine(prod1Id);
}

public static void AddOrderline()
{
// Get a product:
var prod = Context.Products.Find(prod1Id)!;

// Create orderline:
var line = Context.OrderLines.CreateProxy();
/*39*/ line.Product = prod;
/*40*/ var cp = line.Product.CatalogPrice;
line.OrderPrice = cp;
Context.OrderLines.Add(line);

Context.SaveChanges();
Console.WriteLine(line.OrderPrice);
}
}

public class OrderContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connection = new SqliteConnection("Filename=:memory:");
connection.Open();
optionsBuilder.UseSqlite(connection);
optionsBuilder.UseChangeTrackingProxies();
optionsBuilder.UseLazyLoadingProxies();
}

public virtual DbSet OrderLines { get; set; }
public virtual DbSet Products { get; set; }
}

public class OrderLine
{
[Key]
public virtual int Id { get; set; }

public virtual int ProductId { get; set; }

[ForeignKey(nameof(ProductId))]
public virtual required Product Product { get; set; }

public virtual decimal OrderPrice { get; set; }
}

public class Product
{
[Key]
public virtual int Id { get; set; }

public virtual required string Name { get; set; }

public virtual decimal CatalogPrice { get; set; }
}
```

Target framework: .NET 8.0
Included package references:

```





all
runtime; build; native; contentfiles; analyzers; buildtransitive

```

Exception thrown:

```
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at Program.AddOrderline3() in C:\Stuff\EfCoreLazyAddOrder\EfCoreLazyAddOrder\Program.cs:line 40
at Program.Main(String[] args) in C:\Stuff\EfCoreLazyAddOrder\EfCoreLazyAddOrder\Program.cs:line 17
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.