We found this while migrating a production application from SQL Server to PostgreSQL -- a query that had worked correctly on SQL Server started throwing this exception against efcore.pg.
Include your code
using Microsoft.EntityFrameworkCore;
using Npgsql;
using Testcontainers.MsSql;
using Testcontainers.PostgreSql;
var sqlServerContainer = new MsSqlBuilder().Build();
var postgresContainer = new PostgreSqlBuilder().Build();
await sqlServerContainer.StartAsync();
await postgresContainer.StartAsync();
await Run("sqlserver", new SqlServerReproContext(sqlServerContainer.GetConnectionString()));
await Run("postgres", new PostgresReproContext(postgresContainer.GetConnectionString()));
await sqlServerContainer.DisposeAsync();
await postgresContainer.DisposeAsync();
static async Task Run(string label, ReproContext context)
{
await using (context)
{
await context.Database.EnsureCreatedAsync();
const short OrgId = 1;
var orderIdentifier = Guid.NewGuid();
var representative = new Representative { Id = 1, OrgId = OrgId, IsActive = true };
var vendor = new Vendor { Id = 1, OrgId = OrgId, IsActive = true, Representatives = [representative] };
var vendorLink = new VendorLink { Id = 1, OrgId = OrgId, Vendor = vendor };
var order = new Order { Id = 1, OrgId = OrgId, OrderIdentifier = orderIdentifier, VendorLinks = [vendorLink] };
context.Orders.Add(order);
await context.SaveChangesAsync();
Console.WriteLine($"--- {label} ---");
try
{
var result = await context.Orders
.Where(x => x.OrderIdentifier == orderIdentifier)
.Select(x => ValueTuple.Create(
x.Id,
x.VendorLinks.Any(vl => vl.Vendor.IsActive && vl.Vendor.Representatives.Any(r => r.IsActive))))
.FirstOrDefaultAsync();
Console.WriteLine($"SUCCESS: ({result.Item1}, {result.Item2})");
}
catch (Exception ex)
{
Console.WriteLine($"FAILED: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
Console.WriteLine();
}
}
public class Representative
{
public int Id { get; set; }
public short OrgId { get; set; }
public Guid RepresentativeIdentifier { get; set; }
public int VendorId { get; set; }
public bool IsActive { get; set; }
}
public class Vendor
{
public int Id { get; set; }
public short OrgId { get; set; }
public Guid VendorIdentifier { get; set; }
public bool IsActive { get; set; }
public List<Representative> Representatives { get; set; } = [];
}
public class VendorLink
{
public int Id { get; set; }
public short OrgId { get; set; }
public Guid VendorLinkIdentifier { get; set; }
public int OrderId { get; set; }
public int? VendorId { get; set; }
public Vendor? Vendor { get; set; }
}
public class Order
{
public int Id { get; set; }
public short OrgId { get; set; }
public Guid OrderIdentifier { get; set; }
public List<VendorLink> VendorLinks { get; set; } = [];
}
public abstract class ReproContext : DbContext
{
public short OrgId { get; set; } = 1;
public DbSet<Order> Orders => Set<Order>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Representative>().HasKey(e => new { e.OrgId, e.Id });
modelBuilder.Entity<Vendor>(builder =>
{
builder.HasKey(e => new { e.OrgId, e.Id });
builder
.HasMany(v => v.Representatives)
.WithOne()
.HasForeignKey(r => new { r.OrgId, r.VendorId })
.IsRequired();
modelBuilder.Entity<Vendor>().HasQueryFilter(x => x.OrgId == OrgId);
});
modelBuilder.Entity<VendorLink>(builder =>
{
builder.HasKey(e => new { e.OrgId, e.Id });
builder
.HasOne(vl => vl.Vendor)
.WithMany()
.HasForeignKey(vl => new { vl.OrgId, vl.VendorId })
.IsRequired(false);
});
modelBuilder.Entity<Order>(builder =>
{
builder.HasKey(e => new { e.OrgId, e.Id });
builder
.HasMany(o => o.VendorLinks)
.WithOne()
.HasForeignKey(vl => new { vl.OrgId, vl.OrderId })
.IsRequired();
});
}
}
public sealed class SqlServerReproContext(string connectionString) : ReproContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(connectionString);
}
public sealed class PostgresReproContext(string connectionString) : ReproContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
dataSourceBuilder.EnableRecordsAsTuples();
optionsBuilder.UseNpgsql(dataSourceBuilder.Build());
}
}
Include the output of your code
Against SQL Server, the query returns (1, True) as expected.
Against Npgsql, it throws:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.CreateGetValueExpression(ParameterExpression dbDataReader, Int32 index, Boolean nullable, RelationalTypeMapping typeMapping, Type type, IPropertyBase property)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, Expression& relationalCommandResolver, IReadOnlyList`1& readerColumns, LambdaExpression& relatedDataLoaders, Int32& collectionId)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
...
Include provider and version information
EF Core version: 10.0.12
Npgsql.EntityFrameworkCore.PostgreSQL version: 10.0.3
Database server version: PostgreSQL (tested via Testcontainers' default image); also reproduces against Aurora PostgreSQL
Operating system: Windows (also seen in Linux-hosted production)
IDE: n/a (dotnet run)
Further technical details
Removing the query filter on Vendor, or splitting the tuple-projecting query into two separate non-tuple queries, both make it work again.
We found this while migrating a production application from SQL Server to PostgreSQL -- a query that had worked correctly on SQL Server started throwing this exception against efcore.pg.
Include your code
Include the output of your code
Against SQL Server, the query returns
(1, True)as expected.Against Npgsql, it throws:
Include provider and version information
EF Core version: 10.0.12
Npgsql.EntityFrameworkCore.PostgreSQL version: 10.0.3
Database server version: PostgreSQL (tested via Testcontainers' default image); also reproduces against Aurora PostgreSQL
Operating system: Windows (also seen in Linux-hosted production)
IDE: n/a (
dotnet run)Further technical details
Removing the query filter on
Vendor, or splitting the tuple-projecting query into two separate non-tuple queries, both make it work again.