dotnet / dotnet/EntityFramework.Docs
EFCore 6 Table Splitting regression bug with Project <Nullable>disable</Nullable>
- Dominant language
- Mermaid
- Stars
- 1.7k
- Forks
- 2k
- Avg merge
- 7d 23h
- Merged PRs (30d)
- 16
Description
## Table Splitting "OrderDetails" entity returning null when upgrading project from .Net 5 with Nullable disabled
### Bug
- Expected behaviour - DetailedOrder should be returned as it includes non-nullable Status property set to 1 as per guidance https://docs.microsoft.com/en-us/ef/core/modeling/table-splitting
- Actual behaviour - EFCore 6 does not return DetailedOrder (i.e. returns null)
### Setup
- The below code works as expected with EFCore 5, or EFCore 6 when project is configured `enable` (and after changing DetailedOrder.Content to nullable _byte[]?_)
- Exception thrown with EFCore 6 when project is configured `disable` (which is default when upgrading from .Net 5 and older)
### Code
```C#
using Microsoft.EntityFrameworkCore;
using (var db = new DemoDbContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
var order = new Order
{
Status = 1,
DetailedOrder = new DetailedOrder { Status = 1 }
};
db.Add(order);
db.SaveChanges();
var detailedOrder = db.DetailedOrders.FirstOrDefault();
if (detailedOrder == null)
{
throw new Exception("DetailedOrder should be returned due to non-nullable Status");
}
else
{
Console.WriteLine($"Successfully returned {nameof(DetailedOrder)} Id {detailedOrder.Id}");
}
}
public class DemoDbContext : DbContext
{
public DbSet Orders { get; set; }
public DbSet DetailedOrders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite($"Data Source=demodbcontext.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity(dob =>
{
dob.ToTable("Orders");
dob.Property(o => o.Status).HasColumnName("Status");
});
modelBuilder.Entity(ob =>
{
ob.ToTable("Orders");
ob.Property(o => o.Status).HasColumnName("Status");
ob.HasOne(o => o.DetailedOrder).WithOne()
.HasForeignKey(o => o.Id);
});
}
}
public class Order
{
public int Id { get; set; }
public int Status { get; set; }
public DetailedOrder DetailedOrder { get; set; }
}
public class DetailedOrder
{
public int Id { get; set; }
public int Status { get; set; }
public byte[] Content { get; set; }
}
```
### Workaround Notes
Changing project to `enable` is clearly not an acceptable workaround, as it changes the runtime behaviour (as demonstrated here) and can cause other regression bugs (with other frameworks).
With .Net 6 Nullable disabled, even after telling ModelBuilder that `Content` is not required `dob.Property(o => o.Content).IsRequired(false);` does not help
### Include provider and version information
EF Core version: 6.0.6
Database provider: Microsoft.EntityFrameworkCore.Sqlite
Target framework: .NET 6.0 `disable`
Operating system: Win 10
IDE: Visual Studio 2022
Contributor guide
Assessment
This issue has not been assessed yet.