Better exception for incomplete inline instantiation of types
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
Our complex type support (#31460) allows comparing complex types directly:
```c#
_ = await ctx.Foos.Where(f => f.Address == new Address { Street = f.Name, City = "a" }).ToListAsync();
```
```sql
SELECT [f].[Id], [f].[Name], [f].[Address_City], [f].[Address_Street], [f].[OwnedAddress_City], [f].[OwnedAddress_Street]
FROM [Foos] AS [f]
WHERE [f].[Address_City] = N'a' AND [f].[Address_Street] = [f].[Name]
```
However, if one of the properties is omitted in the inline complex type, translation fails:
```c#
_ = await ctx.Foos.Where(f => f.Address == new Address { Street = f.Name }).ToListAsync();
```
```
Unhandled exception. System.InvalidOperationException: Translation of 'EF.Property(new Address{ Street = StructuralTypeShaperExpression:
Foo
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
.Name }
, "City")' failed. Either the query source is not an entity type, or the specified property does not exist on the entity type.
```
It's not immediately clear what should happen here - the CLR default could be used, or we could not generate a comparison for the absent property altogether (though that seems against the LINQ meaning). It may be better to let this throw, requiring all properties to be listed out - but at the very least it would be better to have a clearer exception saying this.
Full repro
```c#
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
_ = await ctx.Foos.Where(f => f.Address == new Address { Street = f.Name }).ToListAsync();
public class BlogContext : DbContext
{
public DbSet Foos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer("Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().ComplexProperty(f => f.Address);
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public Address2 OwnedAddress { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
```
Contributor guide
Assessment
This issue has not been assessed yet.