【.NET新特性·第17篇】EF Core 10 与 Aspire 13.1

LINQ 增强、命名查询过滤器、复杂类型 JSON 映射、Aspire 持续改进------数据访问和云原生开发的最新进展

版本定位

适用版本:.NET 10 | EF Core 10 | Aspire 13.1 前置知识:EF Core 基础、Aspire 基础

背景

EF Core 10 在数据访问方面带来了多项重大改进,包括复杂类型 JSON 映射、命名查询过滤器、批量操作增强等。Aspire 13.1 则继续改进云原生开发体验,新增 Dashboard 增强、Azure/AWS 集成改进以及 Redis 作为 LLM 缓存等能力。

新特性一览

特性 简述 实用性
复杂类型 JSON 映射 将复杂类型映射为 JSON 列 ⭐⭐⭐⭐⭐
命名查询过滤器 多个可独立控制的查询过滤器 ⭐⭐⭐⭐⭐
DbSet 参数支持 集合参数化查询 ⭐⭐⭐⭐
ExecuteUpdate/ExecuteDelete 增强 批量操作支持更多场景 ⭐⭐⭐⭐⭐
交错式 ID 改进 更灵活的主键生成策略 ⭐⭐⭐⭐
SQL Server TIME 类型支持 原生时间类型映射 ⭐⭐⭐
值比较器改进 更精确的变更检测 ⭐⭐⭐⭐
查询翻译改进 更多 LINQ 操作翻译为 SQL ⭐⭐⭐⭐
安全改进 默认禁用敏感数据日志 ⭐⭐⭐⭐
Aspire Dashboard 增强 更好的可观测性体验 ⭐⭐⭐⭐⭐
Aspire + Azure 集成 Azure 服务深度集成 ⭐⭐⭐⭐
Aspire + AWS 集成 AWS 服务深度集成 ⭐⭐⭐
Redis 作为 LLM 缓存 AI 应用缓存方案 ⭐⭐⭐⭐
Aspire 模板改进 更多项目模板 ⭐⭐⭐

EF Core 10 新特性详解

1. 复杂类型 JSON 映射(Complex Type JSON Mapping)

之前的做法:复杂类型需要单独的表或手动序列化

复制代码
// EF Core 9 及之前
public class Order
{
    public int Id { get; set; }
    // 需要单独的表存储地址
    public int ShippingAddressId { get; set; }
    public Address ShippingAddress { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string ZipCode { get; set; }
}

EF Core 10 的做法:将复杂类型直接映射为 JSON 列

复制代码
// EF Core 10
public class Order
{
    public int Id { get; set; }
    // 复杂类型直接存储为 JSON 列
    public Address ShippingAddress { get; set; }
    public Address BillingAddress { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string ZipCode { get; set; }
}

// 配置
modelBuilder.Entity<Order>().ComplexProperty(o => o.ShippingAddress);
modelBuilder.Entity<Order>().ComplexProperty(o => o.BillingAddress);

数据库表结构对比

方案 表结构 查询性能 存储效率
旧方案(关联表) Order + Address 表 JOIN 查询 正常
新方案(JSON 列) Order 表(含 JSON 列) 单表查询 更高

查询示例

复制代码
// 查询 JSON 列中的属性
var orders = await context.Orders
    .Where(o => o.ShippingAddress.City == "Beijing")
    .ToListAsync();

// 更新 JSON 列中的属性
await context.Orders
    .Where(o => o.Id == 1)
    .ExecuteUpdateAsync(s => s
        .SetProperty(o => o.ShippingAddress.City, "Shanghai"));

2. 命名查询过滤器

之前的做法:使用 HasQueryFilter,每个实体只能有一个

复制代码
// EF Core 9 及之前
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
    public void Configure(EntityTypeBuilder<Product> builder)
    {
        // 只能有一个过滤器
        builder.HasQueryFilter(p => p.IsActive);
    }
}

EF Core 10 的做法:命名查询过滤器,支持多个

复制代码
// EF Core 10
public class ProductConfiguration : IEntityTypeConfiguration<Product>
{
    public void Configure(EntityTypeBuilder<Product> builder)
    {
        // 可以有多个命名过滤器
        builder.HasQueryFilter("ActiveFilter", p => p.IsActive);
        builder.HasQueryFilter("RecentFilter", p => p.CreatedAt > DateTime.Now.AddDays(-30));
    }
}

// 使用时可以禁用特定过滤器
var allProducts = await context.Products
    .IgnoreQueryFilters("ActiveFilter")  // 只禁用 ActiveFilter
    .ToListAsync();

3. DbSet 参数支持

之前的做法:使用 Contains 时需要构建列表

复制代码
// EF Core 9 及之前
var ids = new List<int> { 1, 2, 3, 4, 5 };
var products = await context.Products
    .Where(p => ids.Contains(p.Id))
    .ToListAsync();

EF Core 10 的做法:直接使用 DbSet 作为参数

复制代码
// EF Core 10
var categoryIds = context.Categories
    .Where(c => c.Name.StartsWith("Electronics"))
    .Select(c => c.Id);

var products = await context.Products
    .Where(p => categoryIds.Contains(p.CategoryId))
    .ToListAsync();

4. ExecuteUpdate/ExecuteDelete 增强

之前的做法:批量操作功能有限

复制代码
// EF Core 9 及之前
await context.Products
    .Where(p => p.Price < 10)
    .ExecuteUpdateAsync(s => s.SetProperty(p => p.Price, p => p.Price * 1.1m));

EF Core 10 的做法:支持更复杂的批量操作

复制代码
// EF Core 10 - 支持多个 Set 操作
await context.Products
    .Where(p => p.Price < 10)
    .ExecuteUpdateAsync(s => s
        .SetProperty(p => p.Price, p => p.Price * 1.1m)
        .SetProperty(p => p.UpdatedAt, DateTime.UtcNow)
        .SetProperty(p => p.NeedsReview, true));

// 支持删除并返回删除的实体
var deletedProducts = await context.Products
    .Where(p => p.IsDiscontinued)
    .ExecuteDeleteAndReturnAsync();

5. 交错式 ID 改进(Interleaved ID)

复制代码
// EF Core 10 - 更灵活的主键生成
public class Order
{
    // 交错式 ID: tenantId + sequence
    [Key]
    public Guid Id { get; set; }

    public int TenantId { get; set; }
}

// 配置交错式 ID
modelBuilder.Entity<Order>()
    .Property(o => o.Id)
    .HasInterleavedId(o => o.TenantId);

6. SQL Server TIME 类型支持

复制代码
// EF Core 10 - 原生 TIME 类型映射
public class StoreHours
{
    public int Id { get; set; }
    public TimeOnly OpenTime { get; set; }
    public TimeOnly CloseTime { get; set; }
}

// 查询
var openStores = await context.StoreHours
    .Where(s => s.OpenTime <= TimeOnly.FromDateTime(DateTime.Now))
    .Where(s => s.CloseTime >= TimeOnly.FromDateTime(DateTime.Now))
    .ToListAsync();

7. 值比较器改进

复制代码
// EF Core 10 - 更精确的变更检测
public class Money
{
    public decimal Amount { get; set; }
    public string Currency { get; set; }
}

// 自定义值比较器
public class MoneyComparer : ValueComparer<Money>
{
    public MoneyComparer() : base(
        (a, b) => a.Amount == b.Amount && a.Currency == b.Currency,
        m => m.Amount.GetHashCode() ^ m.Currency.GetHashCode(),
        m => new Money { Amount = m.Amount, Currency = m.Currency })
    {
    }
}

// 配置
modelBuilder.Entity<Product>()
    .Property(p => p.Price)
    .Metadata.SetValueComparer(new MoneyComparer());

8. 查询翻译改进

复制代码
// EF Core 10 - 更多 LINQ 操作翻译为 SQL

// 窗口函数支持
var rankedProducts = await context.Products
    .Select(p => new
    {
        p.Name,
        p.Price,
        Rank = EF.Functions.RankOver(
            EF.Functions.PartitionBy(p.Category),
            EF.Functions.OrderBy(p.Price))
    })
    .ToListAsync();

// 更复杂的 GROUP BY
var categoryStats = await context.Products
    .GroupBy(p => p.Category)
    .Select(g => new
    {
        Category = g.Key,
        Count = g.Count(),
        AveragePrice = g.Average(p => p.Price),
        MinPrice = g.Min(p => p.Price),
        MaxPrice = g.Max(p => p.Price)
    })
    .ToListAsync();

9. 安全改进

复制代码
// EF Core 10 - 默认禁用敏感数据日志
// 之前需要手动配置
optionsBuilder.EnableSensitiveDataLogging(false);  // 现在是默认行为

// 如果需要启用,必须显式声明
optionsBuilder.EnableSensitiveDataLogging(true);  // 需要显式启用

Aspire 13.1 新特性详解

1. Dashboard 增强

复制代码
┌─────────────────────────────────────────────────────────┐
│  .NET Aspire Dashboard                                    │
├─────────────────────────────────────────────────────────┤
│  Resources │ Console │ Logs │ Traces │ Metrics │ AI │
├─────────────────────────────────────────────────────────┤
│  api        │ Running │ 127.0.0.1:5000                  │
│  web        │ Running │ 127.0.0.1:5001                  │
│  cache      │ Running │ 127.0.0.1:6379                  │
│  db         │ Running │ 127.0.0.1:5432                  │
│  mq         │ Running │ 127.0.0.1:5672                  │
│  llm-cache  │ Running │ 127.0.0.1:6380                  │
└─────────────────────────────────────────────────────────┘

新增功能

  • AI 追踪面板:可视化 LLM 调用链路和 Token 消耗

  • 资源依赖图:直观展示服务间依赖关系

  • 性能指标仪表盘:实时监控 CPU、内存、请求量

2. Aspire + Azure 集成

复制代码
var builder = DistributedApplication.CreateBuilder(args);

// Azure 服务深度集成
var storage = builder.AddAzureStorage("storage");
var cosmos = builder.AddAzureCosmosDB("cosmos")
    .AddDatabase("mydb");
var serviceBus = builder.AddAzureServiceBus("servicebus");
var appInsights = builder.AddAzureApplicationInsights("insights");

// 自动配置连接字符串和遥测
builder.AddProject<Projects.MyApi>("api")
    .WithReference(storage)
    .WithReference(cosmos)
    .WithReference(serviceBus)
    .WithReference(appInsights);

3. Aspire + AWS 集成

复制代码
var builder = DistributedApplication.CreateBuilder(args);

// AWS 服务支持
var dynamodb = builder.AddAWSDynamoDB("dynamodb");
var sqs = builder.AddAWSSqs("sqs");
var s3 = builder.AddAWSS3("s3");

builder.AddProject<Projects.MyApi>("api")
    .WithReference(dynamodb)
    .WithReference(sqs)
    .WithReference(s3);

4. Redis 作为 LLM 缓存

复制代码
var builder = DistributedApplication.CreateBuilder(args);

// Redis 作为 LLM 缓存
var redis = builder.AddRedis("llm-cache");

// 配置 LLM 服务使用 Redis 缓存
builder.AddProject<Projects.MyAiService>("ai")
    .WithReference(redis)
    .WithEnvironment("LLM_CACHE_TTL", "3600");

使用示例

复制代码
// AI 服务中使用 Redis 缓存
public class AiService
{
    private readonly IDatabase _redis;
    private readonly IChatClient _chatClient;

    public AiService(IDatabase redis, IChatClient chatClient)
    {
        _redis = redis;
        _chatClient = chatClient;
    }

    public async Task<string> GetCompletion(string prompt)
    {
        // 检查缓存
        var cached = await _redis.StringGetAsync($"llm:{prompt.GetHashCode()}");
        if (cached.HasValue)
            return cached.ToString();

        // 调用 LLM
        var result = await _chatClient.CompleteAsync(prompt);

        // 写入缓存
        await _redis.StringSetAsync(
            $"llm:{prompt.GetHashCode()}",
            result.Message.Content,
            TimeSpan.FromHours(1));

        return result.Message.Content;
    }
}

5. Aspire 模板改进

复制代码
# 新增模板
dotnet new list aspire

# Aspire 项目模板
dotnet new aspire-starter     # 完整微服务模板
dotnet new aspire-api         # API 服务模板
dotnet new aspire-redis       # Redis 缓存模板
dotnet new aspire-ai          # AI 服务模板

实战场景

EF Core 10 复杂类型 JSON 映射适合的场景

复制代码
// 配置信息存储
public class AppConfig
{
    public int Id { get; set; }
    public AppSettings Settings { get; set; }
    public NotificationConfig Notifications { get; set; }
}

modelBuilder.Entity<AppConfig>()
    .ComplexProperty(c => c.Settings)
    .ComplexProperty(c => c.Notifications);

Aspire 适合的场景

复制代码
// 微服务架构
var builder = DistributedApplication.CreateBuilder(args);

// 数据库服务
var db = builder.AddPostgreSQL("db")
    .AddDatabase("mydb");

// 缓存服务
var cache = builder.AddRedis("cache");

// 消息队列
var mq = builder.AddRabbitMQ("messaging");

// API 服务
var api = builder.AddProject<Projects.MyApi>("api")
    .WithReference(db)
    .WithReference(cache)
    .WithReference(mq);

// Web 前端
builder.AddProject<Projects.MyWeb>("web")
    .WithReference(api);

迁移建议

EF Core 10 迁移

复制代码
# 1. 更新 NuGet 包
dotnet add package Microsoft.EntityFrameworkCore --version 10.0.0

# 2. 创建迁移
dotnet ef migrations add InitialCreate

# 3. 应用迁移
dotnet ef database update

Aspire 13.1 迁移

复制代码
# 1. 更新 Aspire 模板
dotnet new install Aspire.ProjectTemplates

# 2. 更新项目引用
dotnet add package Aspire.Hosting --version 13.3.3

一句话总结

EF Core 10 的复杂类型 JSON 映射和命名过滤器,加上 Aspire 13.1 的 Azure/AWS 集成与 LLM 缓存支持,让数据访问和云原生 AI 开发更加强大。


官方文档


📦 示例代码:.NET 新特性巡礼全系列配套示例代码(含 dotnet 8/9/10)

💬 欢迎点赞、收藏、转发,你的支持是我持续创作的动力!

相关推荐
zhangzeyuaaa2 小时前
AI Agent 执行引擎选型指南:PowerShell / Bash 和 Python,边界与最佳实践
人工智能·python·bash
泡干脆面就番茄2 小时前
04_EigenFace特征脸PCA人脸识别
python·opencv
今儿敲了吗2 小时前
01词频统计器
笔记·python
今天AI了吗2 小时前
去中心化 AI 反馈系统:数据不上链,凭证与激励分开管
人工智能·windows·python·数据分析·去中心化·区块链·embedding
今朝唯我少年郎2 小时前
Codex安全盲区代码漏洞生成实测
python·程序员
E_ICEBLUE2 小时前
Python 实现 Excel 转 Markdown,支持工作表、单元格区域和批量处理
python·excel·markdown·格式转换
ctlover3 小时前
Python高级与正则表达式
开发语言·python
泡海椒3 小时前
生产环境安全配置:JQuickJavaInvocationGuard自定义防护规则实战
开发语言·python·安全