gpt4 book ai didi

C# 函数返回通用对象/实体

转载 作者:太空狗 更新时间:2023-10-29 23:19:24 27 4
gpt4 key购买 nike

在我的应用程序中,我需要显示不同存储过程返回的记录列表。每个存储过程返回不同类型的记录(即列数和列类型不同)。

我最初的想法是为每种类型的记录创建一个类,并创建一个函数来执行相应的存储过程并返回 List 。像这样:

  public class MyCustomClass1
{
public int Col1 { get; set; } //In reality the columns are NOT called Col1 and Col1 but have proper names
public int Col2 { get; set; }
}

public static List<MyCustomClass1> GetDataForReport1(int Param1)
{

List<MyCustomClass1> output = new List<MyCustomClass1>();

using (SqlConnection cn = new SqlConnection("MyConnectionString"))
using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1;

SqlDataReader rdr=cmd.ExecuteReader();

int Col1_Ordinal = rdr.GetOrdinal("Col1");
int Col2_Ordinal = rdr.GetOrdinal("Col2");

while (rdr.Read())
{
output.Add(new MyCustomClass1
{
Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value,
Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value
});
}
rdr.Close();
}

return output;

}

这工作正常,但因为我不需要在我的客户端代码中操作这些记录(我只需要将它们绑定(bind)到我的应用程序层中的图形控件),所以这样做真的没有意义,因为我最终会得到大量我实际上不会使用的自定义类。我发现这个可以解决问题:

    public static DataTable GetDataForReport1(int Param1)
{

DataTable output = new DataTable();

using (SqlConnection cn = new SqlConnection("MyConnectionString"))
using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1;

output.Load(cmd.ExecuteReader());
}

return output;

}

这将返回一个 DataTable,我可以将其绑定(bind)到我在应用程序层中使用的任何控件。我想知道是否真的需要使用 DataTable。

我不能返回使用匿名类创建的对象列表吗:

    public static List<object> GetDataForReport1(int Param1)
{

List<object> output = new List<object>();

using (SqlConnection cn = new SqlConnection("MyConnectionString"))
using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1;

SqlDataReader rdr=cmd.ExecuteReader();

int Col1_Ordinal = rdr.GetOrdinal("Col1");
int Col2_Ordinal = rdr.GetOrdinal("Col2");

while (rdr.Read())
{
output.Add(new
{
Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value,
Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value
});
}
rdr.Close();
}

return output;

}

还有其他想法吗?基本上我只希望函数返回可以绑定(bind)到图形控件的“东西”,我不想创建自定义类,因为它们不会真正被使用。什么是最好的方法?

最佳答案

好消息是:这不是第一次 entities vs datasets问题出现了。这是一个比我自己的编程经验更古老的争论。如果您不想编写 DTO 或自定义实体,那么您的选择是数据表/数据集,或者您可以重新发明这个轮子。你不会是第一个,也不会是最后一个。 DTO/Entities 的论点是,您没有使用 DataSet 获得的性能开销。 DataSet 必须存储很多关于各个列的数据类型的额外信息,等等......

有一件事,您可能会很高兴听到,如果您采用自定义实体路线并且您很高兴您的对象属性名称与存储过程返回的列名称相匹配,您可以跳过编写所有这些 GetDataForReport() 映射您使用 GetOrdinal 将列映射到属性的函数。幸运的是,一些聪明的猴子已经正确地解决了这个问题here .

编辑:我今天正在研究一个完全不同的问题(将数据集绑定(bind)到 silverlight 数据网格)并遇到了 this article作者 Vladimir Bodurov,展示了如何将 IDictionary 的 IEnumerable 转换为动态创建对象的 IEnumerable(使用 IL)。我突然想到,您可以轻松修改扩展方法以接受数据读取器而不是 IDictionary 的 IEnumerable 来解决您的动态集合问题。它太酷了。我认为它会完全完成您所追求的,因为您不再需要数据集或自定义实体。实际上,您最终得到了一个自定义实体集合,但您失去了编写实际类的开销。

如果你很懒,这里有一个方法可以将数据读取器转换为 Vladimir 的字典集合(它比实际转换他的扩展方法效率低):

public static IEnumerable<IDictionary> ToEnumerableDictionary(this IDataReader dataReader)
{
var list = new List<Dictionary<string, object>>();
Dictionary<int, string> keys = null;
while (dataReader.Read())
{
if(keys == null)
{
keys = new Dictionary<int, string>();
for (var i = 0; i < dataReader.FieldCount; i++)
keys.Add(i, dataReader.GetName(i));
}
var dictionary = keys.ToDictionary(ordinalKey => ordinalKey.Value, ordinalKey => dataReader[ordinalKey.Key]);
list.Add(dictionary);
}
return list.ToArray();
}

关于C# 函数返回通用对象/实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1807899/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com