EntityFrameworkCore.InterfaceSets
1.0.1
See the version list below for details.
dotnet add package EntityFrameworkCore.InterfaceSets --version 1.0.1
NuGet\Install-Package EntityFrameworkCore.InterfaceSets -Version 1.0.1
<PackageReference Include="EntityFrameworkCore.InterfaceSets" Version="1.0.1" />
<PackageVersion Include="EntityFrameworkCore.InterfaceSets" Version="1.0.1" />
<PackageReference Include="EntityFrameworkCore.InterfaceSets" />
paket add EntityFrameworkCore.InterfaceSets --version 1.0.1
#r "nuget: EntityFrameworkCore.InterfaceSets, 1.0.1"
#:package EntityFrameworkCore.InterfaceSets@1.0.1
#addin nuget:?package=EntityFrameworkCore.InterfaceSets&version=1.0.1
#tool nuget:?package=EntityFrameworkCore.InterfaceSets&version=1.0.1
EntityFrameworkCore.InterfaceSets
A library for Entity Framework Core that enables querying entities through shared interfaces, allowing you to work with entities from different class hierarchies that implement a common interface.
Features
- Interface-based querying: Query multiple entity types through a shared interface
- Automatic discovery: Automatically finds all entity types implementing an interface
- LINQ support: Full LINQ query support with
Where,OrderBy,Select, etc. - Async enumeration: Full support for async operations
- Type-safe: Compile-time type safety with generic constraints
Usage
Define your interfaces and entities
public interface IArchivable
{
bool IsArchived { get; set; }
DateTime? ArchivedAt { get; set; }
}
public class Document : IArchivable
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsArchived { get; set; }
public DateTime? ArchivedAt { get; set; }
}
public class Product : IArchivable
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsArchived { get; set; }
public DateTime? ArchivedAt { get; set; }
}
Query across multiple entity types
// Get all archived items across all entity types
var archivedItems = context.InterfaceSet<IArchivable>()
.Where(x => x.IsArchived)
.OrderBy(x => x.ArchivedAt)
.ToList();
// Use async enumeration
await foreach (var item in context.InterfaceSet<IArchivable>())
{
Console.WriteLine($"Archived: {item.IsArchived}");
}
// Access specific DbSet if needed
var interfaceSet = context.InterfaceSet<IArchivable>();
var documentDbSet = interfaceSet.GetDbSet<Document>();
Limitations
InterfaceSet<TInterface> is designed as a read-only query interface. The following operations are not supported:
Add(),Remove(),Update()- these would be ambiguous across multiple entity types- Change tracking operations
- Some navigation property operations
To modify entities, use the specific DbSet<TEntity> or call GetDbSet<TEntity>() on the InterfaceSet.
Entity Hierarchies
The library correctly handles entity inheritance hierarchies. When you have a base type implementing an interface and derived types, the library automatically:
- Only queries the root type in the hierarchy to avoid duplicates
- Returns all derived types automatically (EF Core's normal behavior)
public class BaseDocument : IArchivable { }
public class Invoice : BaseDocument { } // Inherits IArchivable
public class Contract : BaseDocument { } // Inherits IArchivable
// DbContext
public DbSet<BaseDocument> BaseDocuments { get; set; }
public DbSet<Invoice> Invoices { get; set; }
public DbSet<Contract> Contracts { get; set; }
// InterfaceSet will only query BaseDocument (not Invoice/Contract separately)
// This prevents duplicates while still returning all Invoice and Contract instances
var allDocs = context.InterfaceSet<IArchivable>().ToList();
How it works
Under the hood, the library:
- Scans the
DbContext.Modelto find all entity types implementing the interface - Filters to only root types in entity hierarchies to prevent duplicates
- Creates a combined enumerable that iterates over each DbSet
- Wraps the result as
IQueryable<TInterface>for LINQ support - Provides async enumeration support through
IAsyncEnumerable<TInterface>
Note: Since EF Core doesn't support SQL UNION across different entity types, queries are executed separately for each entity type and combined in memory.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- Microsoft.EntityFrameworkCore (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Performance improvements and fix for interfaces on basetypes not in the model