dotnet / dotnet/efcore

Fully support parameterized and inline lists of entity types in queries

Open
#37,227 0 comments 10 reactions 0 assignees View on GitHub
area-query
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Support the following:

```c#
List posts =
[
new() { Title = "First Post", Views = 100 },
new() { Title = "Second Post", Views = 250 }
];

// The following does a simple "entity equality contains", comparing keys
// (not that composite keys are not supported)
// WHERE [p].[Id] IN (@entity_equality_posts_Id1, @entity_equality_posts_Id2)
// _ = await context.Posts.Where(p => posts.Contains(p)).ToListAsync();

var q = await context.Posts
.Join(posts, p => p.Title, p => p.Title, (ur, cr) => ur)
.ToListAsync();
```

We could translate `posts` to a SQL VALUES expression containing parameters (or constants for inline collection instead of paramerized ones). Note that we do allow a such parameterized/inline collections for Contains only, translating to IN over a single key property (composite keys are not supported).

The VALUES translation would produce dynamic SQL (it would change based on the number of elements in the array). However, we already do that for Contains - this doesn't seem any different.

See similar issue but for complex types rather than for top-level entity types: #36468.
We also have various issues about supporting tuples in this context, e.g. #11799.

Full code sample

```c#
await using var context = new BlogContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

List posts =
[
new() { Title = "First Post", Views = 100 },
new() { Title = "Second Post", Views = 250 }
];

// The following does a simple "entity equality contains", comparing keys
// (not that composite keys are not supported)
// WHERE [p].[Id] IN (@entity_equality_posts_Id1, @entity_equality_posts_Id2)
// _ = await context.Posts.Where(p => posts.Contains(p)).ToListAsync();

// Doesn't currently work.
var q = await context.Posts
.Join(posts, p => p.Title, p => p.Title, (ur, cr) => ur)
.ToListAsync();

public class BlogContext : DbContext
{
public DbSet Posts { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(Environment.GetEnvironmentVariable("Test__SqlServer__DefaultConnection"))
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
}

public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public int Views {get; set;}
}
```

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.