You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用EF Power Tools序列化时遇InvalidOperationException的解决咨询

解决DbContext扩展方法执行时的InvalidOperationException异常

问题重现

使用以下DbContext扩展方法执行SQL操作时,抛出System.InvalidOperationException:

public static class DbContextExtensions
{
public static async Task<List<T>> SqlQueryAsync(this DbContext db, string sql, object[] parameters = null, CancellationToken cancellationToken = default) where T : class
{
if (parameters is null)
{
parameters = new object[] { };
}

    if (typeof(T).GetProperties().Any())
    {
        return await db.Set<T>().FromSqlRaw(sql, parameters).ToListAsync(cancellationToken);
    }
    else
    {
        await db.Database.ExecuteSqlRawAsync(sql, parameters, cancellationToken);
        return default;
    }
}
}

错误信息:

System.InvalidOperationException: The type 'System.Threading.ExecutionContext&' of property 'Context' on type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder1+AsyncStateMachineBox1[System.Collections.Generic.List`1[SpiritWMSApiCore2.Models.Unitech_ASNInfo_BOLResult],SpiritWMSApiCore2.Models.SIRISContextProcedures+<Unitech_ASNInfo_BOLAsync>d__56]' is invalid for serialization or deserialization because it is a pointer type, is a ref struct, or contains generic parameters that have not been replaced by specific types.

问题分析

错误核心原因:

  1. 扩展方法中通过typeof(T).GetProperties().Any()判断是否执行查询的逻辑完全错误——EF Core的FromSqlRaw仅支持映射到数据库对象的合法实体类型,该判断无法区分实体类型和其他非法类型。
  2. 当调用逻辑出现上下文混乱(比如异步状态机类型被错误关联到泛型参数T),EF Core会尝试序列化包含引用结构体(如ExecutionContext&)的类型,触发序列化校验失败。

解决方案

1. 拆分扩展方法,分离查询与非查询逻辑

将查询实体和执行非查询SQL的操作拆分为两个独立方法,避免逻辑混淆:

public static class DbContextExtensions
{
    /// <summary>
    /// 执行SQL查询,返回实体列表(仅支持EF Core已配置的实体类型)
    /// </summary>
    public static async Task<List<T>> SqlQueryAsync<T>(this DbContext db, string sql, object[] parameters = null, CancellationToken cancellationToken = default) 
        where T : class
    {
        parameters ??= Array.Empty<object>();
        return await db.Set<T>().FromSqlRaw(sql, parameters).ToListAsync(cancellationToken);
    }

    /// <summary>
    /// 执行非查询SQL语句(如INSERT/UPDATE/DELETE),返回受影响行数
    /// </summary>
    public static async Task<int> ExecuteSqlAsync(this DbContext db, string sql, object[] parameters = null, CancellationToken cancellationToken = default)
    {
        parameters ??= Array.Empty<object>();
        return await db.Database.ExecuteSqlRawAsync(sql, parameters, cancellationToken);
    }
}

2. 规范调用方式

  • 查询实体时,明确指定合法的EF实体类型:
    var result = await db.SqlQueryAsync<Unitech_ASNInfo_BOLResult>(yourSqlString, parametersArray);
    
  • 执行非查询操作时,调用专门的方法:
    int affectedRows = await db.ExecuteSqlAsync(yourNonQuerySql, parametersArray);
    

3. 额外注意事项

  • 确保泛型参数T是EF Core中已配置的实体类型(存在对应的DbSet<T>或通过Fluent API完成映射),禁止传入匿名类型、包含引用结构体/指针类型的对象。
  • 避免在异步方法中出现泛型参数上下文混乱的情况,确保调用时T的类型明确指向目标实体。

内容的提问来源于stack exchange,提问作者sagesky36

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 01:52:40