EntityFrameworkCore.InterfaceSets
1.0.0
See the version list below for details.
dotnet add package EntityFrameworkCore.InterfaceSets --version 1.0.0
NuGet\Install-Package EntityFrameworkCore.InterfaceSets -Version 1.0.0
<PackageReference Include="EntityFrameworkCore.InterfaceSets" Version="1.0.0" />
<PackageVersion Include="EntityFrameworkCore.InterfaceSets" Version="1.0.0" />
<PackageReference Include="EntityFrameworkCore.InterfaceSets" />
paket add EntityFrameworkCore.InterfaceSets --version 1.0.0
#r "nuget: EntityFrameworkCore.InterfaceSets, 1.0.0"
#:package EntityFrameworkCore.InterfaceSets@1.0.0
#addin nuget:?package=EntityFrameworkCore.InterfaceSets&version=1.0.0
#tool nuget:?package=EntityFrameworkCore.InterfaceSets&version=1.0.0
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.
Initial release with support for interface-based querying across multiple entity types.