C# SQLDataReader 按列名访问

C# SQLDataReader accessing by column name

我有一个 Visual Basic 应用程序,其中我连接到 MS SQL 数据库。我有定义 SqlDataReader、打开连接并执行 ExecuteReader() 命令的代码。我使用以下代码从 reader

检索数据
While myDataReader.Read()
    Session("menu_PEO") = myDataReader("menu_PEO")
    Session("menu_Transfer") = myDataReader("menu_Transfer")
    Session("menu_Loan") = myDataReader("menu_loan")
End While

menu_PEO、menu_Transfer 和 menu_loan 是 SQL returns.

数据中的 3 个列标题

我现在的任务是将代码转换为 C#。我在 c# 中有以下有效的代码:

while (dataReader.Read())
{
    dbMenuPEO = dataReader.GetString(1);
    dbMenuTransfer = dataReader.GetString(2);
    dbMenuLoan = dataReader.GetString(3);
}

由于我的 SQL 是 SELECT *,我无法保证返回数据的顺序,所以我不想依赖于指定 GetString 的实例。

在 C# 中是否有一种方法可以指定我想要检索的列名称,类似于它在 Visual Basic 中的工作方式?

谢谢!

有两种方法可以做到这一点。简单的方法是使用命名索引器:

dbMenuPEO = (string)dataReader["menu_PEO"];

这与以下基本相同:

dbMenuPEO = (string)dataReader.GetValue(dataReader.GetOrdinal("menu_PEO"));

您可以将序号查找移到循环之外,这样效率更高一些。您还可以使用避免强制转换的强类型访问器。这在读取值类型(int、dateTime 等)时可能很重要,因为它避免了需要将值装箱,而 GetValue 会发生这种情况。

var menuPeoIdx = dataReader.GetOrdinal("menu_PEO");
while(dataReader.Read())
{
   dbMenuPEO = dataReader.GetString(menuPeoIdx);
}

通常,您应该永远不要在生产系统中使用select *。始终明确列出您想要的列。原因是它允许更改基础表而无需修复使用代码或过度选择不需要的列。 Select * 是“探索”数据集的绝佳工具,但只能用作开发工具。

I have code which defines a SqlDataReader, opens the connection, and executes the ExecuteReader()

这难道不是必须编写的最繁琐的代码吗?许多人已经想到了这一点,并且发明了许多东西来让你摆脱它的单调乏味。 MarkPflug 的回答直接解决了您的问题,但以防万一您不知道可以显着提高生产力,我想向您介绍其中一种技术

Is there a way in c# to specify the column name that I would like to retrieve similar to the way it works in Visual Basic?

这是一种方法,因为当您这样做时您不必键入它。它避免再次输入您已经输入的相同内容(两次 - 一次用于变量名称,一次在 SQL)

使用visual studio内置的nuget package manager来安装Dapper

然后假设您有一个 class 来保存您的数据:

//C#
record DbMenu(string DbMenuPEO, string DbMenuTransfer, string DbMenuLoan);

'or VB, if you like that sort of thing
Class DbMenu
  Public Property DbMenuPEO as String
  Public Property DbMenuTransfer As String
  Public Property DbMenuLoan As String
End Class

您可以让 Dapper 进行查询、添加任何参数、打开您的连接、下载您的数据、填写一个包含您的 classes 的列表、关闭连接并 return 它.. 全部在一行代码中:

//C#
using var conn = ... //code here that gets a connection; doesn't need to be open
var myListOfDbMenus = conn.Query<DbMenu>("SELECT * FROM ... ");

'VB
Using conn = ...
  Dim myListOfDbMenus = conn.Query(Of DbMenu)("SELECT * FROM ... ");
End Using

简短的版本是:您的 c# class 属性的名称应与列的名称相同。如果不是,最简单的方法是在 SQL 中使用 AS xyz 来平衡名称。如果要编写参数化查询,请提供 @parameterNames 与您在查询时同时传递的匿名对象的 属性 名称相同:

var q = conn.Query<Type>("SELECT ... WHERE col = @val1", new {val1 = "hello" } );

如果您喜欢编写 SQL 并且水平较低 control/don 不想使用像 EF 这样的 ORM,那么 Dapper 可以让您直接像您一样继续执行 SQL正在做,但去掉了所有重复的周围样板

SQLDataReader class 公开了一组实例方法,允许检索特定类型字段的值,例如 GetInt32()GetString(),可以与 GetOrdinal() 方法结合使用

例子

dataReader.GetString(dataReader.GetOrdinal("YOUR FIELD NAME HERE"))