Facet.Extensions.EFCore
2.4.7
dotnet add package Facet.Extensions.EFCore --version 2.4.7
NuGet\Install-Package Facet.Extensions.EFCore -Version 2.4.7
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Facet.Extensions.EFCore" Version="2.4.7" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Facet.Extensions.EFCore" Version="2.4.7" />
<PackageReference Include="Facet.Extensions.EFCore" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Facet.Extensions.EFCore --version 2.4.7
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Facet.Extensions.EFCore, 2.4.7"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Facet.Extensions.EFCore@2.4.7
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Facet.Extensions.EFCore&version=2.4.7
#tool nuget:?package=Facet.Extensions.EFCore&version=2.4.7
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Facet.Extensions.EFCore
EF Core async extension methods for the Facet library, enabling one-line async mapping and projection between your domain entities and generated facet types.
Key Features
Forward Mapping: Entity → Facet DTO
- Async projection to
List<TTarget>
:ToFacetsAsync<TSource,TTarget>()
orToFacetsAsync<TTarget>()
- Async projection to first or default:
FirstFacetAsync<TSource,TTarget>()
orFirstFacetAsync<TTarget>()
- Async projection to single:
SingleFacetAsync<TSource,TTarget>()
orSingleFacetAsync<TTarget>()
- Async projection to
Reverse Mapping: Facet DTO → Entity (NEW!)
- Selective entity updates:
UpdateFromFacet<TEntity,TFacet>()
- Async entity updates:
UpdateFromFacetAsync<TEntity,TFacet>()
- Update with change tracking:
UpdateFromFacetWithChanges<TEntity,TFacet>()
- Selective entity updates:
All methods leverage your already generated ctor or Projection property and require EF Core 6+.
Getting Started
1. Install packages
dotnet add package Facet.Extensions.EFCore
2. Import namespaces
using Facet.Extensions.EFCore; // for async EF Core extension methods
Forward Mapping (Entity → DTO)
3. Use async mapping in EF Core
// Async projection to list (source type inferred)
var dtos = await dbContext.People.ToFacetsAsync<PersonDto>();
// Async projection to first or default (source type inferred)
var firstDto = await dbContext.People.FirstFacetAsync<PersonDto>();
// Async projection to single (source type inferred)
var singleDto = await dbContext.People.SingleFacetAsync<PersonDto>();
// Legacy explicit syntax still supported
var dtosExplicit = await dbContext.People.ToFacetsAsync<Person, PersonDto>();
Reverse Mapping (DTO → Entity)
4. Use selective entity updates
// Define update DTO (excludes sensitive/immutable properties)
[Facet(typeof(User), "Password", "CreatedAt")]
public partial class UpdateUserDto { }
// API Controller
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(int id, UpdateUserDto dto)
{
var user = await context.Users.FindAsync(id);
if (user == null) return NotFound();
// Only updates properties that actually changed
user.UpdateFromFacet(dto, context);
await context.SaveChangesAsync();
return NoContent();
}
5. Advanced scenarios
// With change tracking for auditing
var result = user.UpdateFromFacetWithChanges(dto, context);
if (result.HasChanges)
{
logger.LogInformation("User {UserId} updated. Changed: {Properties}",
user.Id, string.Join(", ", result.ChangedProperties));
}
// Async version (for future extensibility)
await user.UpdateFromFacetAsync(dto, context);
Complete Example
// Domain entity
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public DateTime CreatedAt { get; set; } // Immutable
public string InternalNotes { get; set; } // Sensitive
}
// Read DTO (for GET operations)
[Facet(typeof(Product), "InternalNotes")]
public partial class ProductDto { }
// Update DTO (for PUT operations - excludes immutable/sensitive fields)
[Facet(typeof(Product), "Id", "CreatedAt", "InternalNotes")]
public partial class UpdateProductDto { }
// API Controller
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly ApplicationDbContext _context;
public ProductsController(ApplicationDbContext context)
{
_context = context;
}
// GET: Forward mapping (Entity -> DTO)
[HttpGet]
public async Task<ActionResult<IEnumerable<ProductDto>>> GetProducts()
{
return await _context.Products
.Where(p => p.IsActive)
.ToFacetsAsync<ProductDto>(); // Source type inferred
}
[HttpGet("{id}")]
public async Task<ActionResult<ProductDto>> GetProduct(int id)
{
var product = await _context.Products
.Where(p => p.Id == id)
.FirstFacetAsync<ProductDto>(); // Source type inferred
return product == null ? NotFound() : product;
}
// PUT: Reverse mapping (DTO -> Entity)
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProduct(int id, UpdateProductDto dto)
{
var product = await _context.Products.FindAsync(id);
if (product == null) return NotFound();
// Selective update - only changed properties
var result = product.UpdateFromFacetWithChanges(dto, _context);
if (result.HasChanges)
{
await _context.SaveChangesAsync();
// Optional: Log what changed
logger.LogInformation("Product {ProductId} updated. Changed: {Properties}",
id, string.Join(", ", result.ChangedProperties));
}
return NoContent();
}
}
API Reference
Method | Description | Use Case |
---|---|---|
ToFacetsAsync<TTarget>() |
Project query to DTO list (source inferred) | GET endpoints |
ToFacetsAsync<TSource, TTarget>() |
Project query to DTO list (explicit types) | Legacy/explicit typing |
FirstFacetAsync<TTarget>() |
Get first DTO or null (source inferred) | GET single item |
FirstFacetAsync<TSource, TTarget>() |
Get first DTO or null (explicit types) | Legacy/explicit typing |
SingleFacetAsync<TTarget>() |
Get single DTO (source inferred) | GET unique item |
SingleFacetAsync<TSource, TTarget>() |
Get single DTO (explicit types) | Legacy/explicit typing |
UpdateFromFacet<TEntity, TFacet>() |
Selective entity update | PUT/PATCH endpoints |
UpdateFromFacetWithChanges<TEntity, TFacet>() |
Update with change tracking | Auditing scenarios |
UpdateFromFacetAsync<TEntity, TFacet>() |
Async selective update | Future extensibility |
Requirements
- Facet v1.6.0+
- Entity Framework Core 6+
- .NET 6+
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. 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 is compatible. 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- Facet.Extensions (>= 2.4.7)
- Microsoft.EntityFrameworkCore (>= 8.0.0)
-
net9.0
- Facet.Extensions (>= 2.4.7)
- Microsoft.EntityFrameworkCore (>= 9.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.
Version | Downloads | Last Updated |
---|---|---|
2.4.7 | 21 | 9/1/2025 |
2.4.6 | 24 | 9/1/2025 |
2.4.5 | 99 | 8/30/2025 |
2.4.4 | 194 | 8/27/2025 |
2.4.3 | 153 | 8/27/2025 |
2.4.2 | 156 | 8/27/2025 |
2.4.0 | 158 | 8/26/2025 |
2.3.0 | 448 | 8/20/2025 |
2.2.0 | 124 | 8/20/2025 |
2.1.0 | 165 | 8/18/2025 |
2.0.1 | 329 | 8/5/2025 |
2.0.0 | 157 | 8/4/2025 |
1.9.3 | 123 | 7/4/2025 |
1.9.1 | 144 | 7/3/2025 |
1.9.0 | 149 | 7/3/2025 |
1.8.0 | 156 | 6/4/2025 |
1.7.0 | 150 | 6/3/2025 |