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

C#/WPF中使用DbContext.ExecuteStoreQuery返回自定义元组的问题

解决ExecuteStoreQuery返回自定义类型或Tuple的问题

这个问题我之前也碰到过,咱们一步步拆解原因,再给出可行的解决方案:

一、为什么自定义类的结果为空?

你当前的SqlTwoStringsClass用的是公共字段,但EF的ExecuteStoreQuery默认只会映射目标类型的公共属性(带get; set;的那种),而且要求属性名称和查询返回的列名完全匹配(大小写不敏感,但最好一致)。你的字段text1、text2既不是属性,名称也和查询里的str1、str2不对应,所以EF没法把查询结果赋值进去,自然就是空的。

二、为什么Tuple会抛出初始化异常?

Tuple<string, string>是不可变类型:它没有无参构造函数,而且Item1、Item2是只读属性。EF需要通过反射创建对象实例并设置属性值,但Tuple的设计不允许这样操作,所以会抛出初始化异常。Tuple不适合作为EF查询的直接返回类型。

三、正确的实现方式

方案1:修复自定义DTO类(推荐)

创建一个标准的DTO类,用公共属性,确保属性名和查询列名对应(或者用SQL别名适配):

namespace MyApp {
    // 推荐设为public,方便跨程序集使用,同一程序集internal也可以
    public class SqlTwoStringsDto {
        // 属性名和查询的列名一致,EF会自动映射
        public string str1 { get; set; }
        public string str2 { get; set; }
    }
}

然后查询代码保持不变,只需要替换类型:

string sql_Select_From_MY_TABLE = "SELECT DISTINCT [str1], [str2] FROM [GP].[dbo].[MY_TABLE] WHERE ID = {0} AND ID2 IS NOT NULL";
ObjectResult<SqlTwoStringsDto> sqlResult = myDbContext.ExecuteStoreQuery<SqlTwoStringsDto>(sql_Select_From_MY_TABLE, someID);

foreach (SqlTwoStringsDto item in sqlResult) {
    Utils.printToConsole(item.str1 + ", " + item.str2);
}

如果不想修改类的属性名,也可以在SQL里给列加别名,适配类的属性:

SELECT DISTINCT [str1] AS text1, [str2] AS text2 FROM [GP].[dbo].[MY_TABLE] WHERE ID = {0} AND ID2 IS NOT NULL

对应的DTO类:

public class SqlTwoStringsDto {
    public string text1 { get; set; }
    public string text2 { get; set; }
}

方案2:手动映射到Tuple(不推荐,适合临时场景)

如果一定要用Tuple,可以手动读取查询结果并创建Tuple:

string sql_Select_From_MY_TABLE = "SELECT DISTINCT [str1], [str2] FROM [GP].[dbo].[MY_TABLE] WHERE ID = {0} AND ID2 IS NOT NULL";
var reader = myDbContext.ExecuteStoreQuery<System.Data.Common.DbDataRecord>(sql_Select_From_MY_TABLE, someID).GetEnumerator();

while (reader.MoveNext()) {
    var resultTuple = Tuple.Create(
        (string)reader.Current["str1"],
        (string)reader.Current["str2"]
    );
    Utils.printToConsole(resultTuple.Item1 + ", " + resultTuple.Item2);
}

或者用DbContext的Database.SqlQuery结合LINQ映射:

var sql = "SELECT DISTINCT [str1], [str2] FROM [GP].[dbo].[MY_TABLE] WHERE ID = @p0 AND ID2 IS NOT NULL";
var tupleList = myDbContext.Database.SqlQuery<object[]>(sql, someID)
    .Select(row => Tuple.Create((string)row[0], (string)row[1]))
    .ToList();

foreach (var tuple in tupleList) {
    Utils.printToConsole(tuple.Item1 + ", " + tuple.Item2);
}

总结

对于这类自定义查询结果,使用专门的DTO类是最佳实践——代码更清晰、易维护,EF也能自动完成映射,避免手动处理数据的繁琐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:16:21