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

如何通过context.ExecuteQuery将SQL Server动态Pivot数据传入Visual Studio

解决SQL Server动态Pivot存储过程在C#中处理动态列的问题

你遇到的核心问题是LINQ to SQL的ExecuteQuery<dynamic>返回的动态对象无法通过TypeDescriptor.GetProperties获取属性——它返回的不是真正的ExpandoObject,而是LINQ to SQL内部封装的动态类型,直接导致你的内层循环根本执行不了。下面给你两个可行的解决方案:

方案1:改用DataTable接收动态结果(推荐)

DataTable天生支持动态列结构,能完美适配存储过程返回的不固定列,之后再把DataTable转换成你需要的List<Dictionary<string, object>>:

public List<Dictionary<string, object>> Neg_conceptos_nomina_pivote(string Vaux_cia, DateTime Vaux_Fecini, DateTime Vaux_fecfin, string VauxCcostos, bool Vaux_abierta_cerrada, bool Vaux_checkDeducciones)
{
    List<Dictionary<string, object>> resultado = new List<Dictionary<string, object>>();
    
    // 直接用SqlConnection操作,避开LINQ to SQL的动态类型限制
    using (Dat_GrupoFaroDBDataContext contexto_grupofaro = new Dat_GrupoFaroDBDataContext())
    using (SqlConnection conn = new SqlConnection(contexto_grupofaro.Connection.ConnectionString))
    {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand("uspconceptos_nomina_pivote", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            // 必须用参数化查询,彻底避免SQL注入风险!
            cmd.Parameters.AddWithValue("@Vaux_cia", Vaux_cia);
            cmd.Parameters.AddWithValue("@Vaux_Fecini", Vaux_Fecini);
            cmd.Parameters.AddWithValue("@Vaux_fecfin", Vaux_fecfin);
            cmd.Parameters.AddWithValue("@Vaux_abierta_cerrada", Vaux_abierta_cerrada);
            cmd.Parameters.AddWithValue("@Vaux_checkDeducciones", Vaux_checkDeducciones);
            
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                DataTable dt = new DataTable();
                dt.Load(reader);
                
                // 将DataTable逐行转换为字典
                foreach (DataRow row in dt.Rows)
                {
                    Dictionary<string, object> rowDict = new Dictionary<string, object>();
                    foreach (DataColumn col in dt.Columns)
                    {
                        rowDict.Add(col.ColumnName, row[col] ?? DBNull.Value);
                    }
                    resultado.Add(rowDict);
                }
            }
        }
    }
    
    return resultado;
}

方案2:修复原ExpandoObject的处理逻辑

如果你坚持要用LINQ to SQL的方式,可以通过反射读取动态对象的属性,替代TypeDescriptor.GetProperties:

public List<Dictionary<string, object>> Neg_conceptos_nomina_pivote(string Vaux_cia, DateTime Vaux_Fecini, DateTime Vaux_fecfin, string VauxCcostos, bool Vaux_abierta_cerrada, bool Vaux_checkDeducciones)
{
    List<Dictionary<string, object>> resultado = new List<Dictionary<string, object>>();
    using (Dat_GrupoFaroDBDataContext contexto_grupofaro = new Dat_GrupoFaroDBDataContext())
    {
        // 先改成参数化查询,杜绝SQL注入!
        var resul = contexto_grupofaro.ExecuteQuery<dynamic>(
            "uspconceptos_nomina_pivote @0, @1, @2, @3, @4",
            Vaux_cia, Vaux_Fecini, Vaux_fecfin, Vaux_abierta_cerrada, Vaux_checkDeducciones);
            
        foreach (var item in resul)
        {
            IDictionary<string, object> resultadoitem = new ExpandoObject();
            // 用反射获取动态对象的公开属性
            var properties = item.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (var prop in properties)
            {
                var value = prop.GetValue(item);
                resultadoitem.Add(prop.Name, value);
            }
            resultado.Add(new Dictionary<string, object>(resultadoitem));
        }
        return resultado;
    }
}

关键提醒:SQL注入风险

你原来的代码直接拼接SQL字符串,存在非常严重的SQL注入漏洞!上面两个方案都改用了参数化查询,一定要坚持这种写法,绝对不要把用户输入直接拼进SQL语句里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:38:25