简体   繁体   English

C# SQLDataReader 按列名访问

[英]C# SQLDataReader accessing by column name

I have a Visual Basic application where I have a connection to a MS SQL database.我有一个 Visual Basic 应用程序,我在其中连接到 MS SQL 数据库。 I have code which defines a SqlDataReader, opens the connection, and executes the ExecuteReader() command.我有定义 SqlDataReader、打开连接并执行 ExecuteReader() 命令的代码。 I use the following code to retrieve the data from the 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, and menu_loan are 3 of the column headings in the data that the SQL returns. menu_PEO、menu_Transfer 和 menu_loan 是 SQL 返回的数据中的 3 个列标题。

I am now tasked with converting the code to c#.我现在的任务是将代码转换为 c#。 I have the following code in c# which works:我在 c# 中有以下代码,它有效:

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

Since my SQL is a SELECT *, I can not guarantee the order of the data being returned so I dont want to rely on specifying the instance of the GetString.由于我的 SQL 是 SELECT *,我不能保证返回数据的顺序,所以我不想依赖指定 GetString 的实例。

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? c# 中是否有一种方法可以指定我想要检索的列名,类似于它在 Visual Basic 中的工作方式?

Thanks!谢谢!

There are two ways to do this.有两种方法可以做到这一点。 The easy way is to use the named indexer:简单的方法是使用命名索引器:

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

Which is essentially the same as:这与以下内容基本相同:

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

You can move the ordinal lookup outside of the loop, which is a bit more efficient.您可以将序数查找移到循环之外,这样效率更高。 You can also use the the strongly-typed accessor which avoids the cast.您还可以使用避免强制转换的强类型访问器。 This can be important when reading value types (int, dateTime, etc) as it avoid needing to box the value, which would happen with GetValue.这在读取值类型(int、dateTime 等)时可能很重要,因为它避免了对值进行装箱,GetValue 会发生这种情况。

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

Generally, you should never use select * in a production system.通常,您永远不应该在生产系统中使用select * Always explicitly list the columns you want.始终明确列出您想要的列。 The reason is that it allows the underlying tables to change without having to fix the consuming code, or over-selecting columns that you don't need.原因是它允许更改基础表,而无需修复使用代码或过度选择您不需要的列。 Select * is a great tool for "exploring" a data set, but should only be used as a dev tool. Select *是“探索”数据集的绝佳工具,但只能用作开发工具。

I have code which defines a SqlDataReader, opens the connection, and executes the ExecuteReader()我有定义 SqlDataReader、打开连接并执行 ExecuteReader() 的代码

And isn't it the most incredibly tedious code to have to write?这不是必须编写的最令人难以置信的乏味代码吗? Many people have thought this over the time and many things have been invented to relieve you of the tedium of it.随着时间的推移,许多人都想到了这一点,并且发明了许多东西来减轻您的乏味。 MarkPflug's answer directly addresses your question, but just in case you aren't aware that there are significant productivity boosts available I'd like to introduce you to one of these technologies 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? c# 中是否有一种方法可以指定我想要检索的列名,类似于它在 Visual Basic 中的工作方式?

Here's a way to do it, in that when you do this you don't have to type it.这是一种方法,当你这样做时,你不必输入它。 It avoids typing the same thing again that you've already typed (twice - once for the variable name, once in the SQL)它避免再次输入您已经输入的相同内容(两次 - 一次用于变量名,一次在 SQL 中)

Use the nuget package manager built into visual studio, to install Dapper使用 Visual Studio 内置的nuget package 管理器安装 Dapper

Then lets say you have a class that holds your data:然后假设您有一个保存数据的 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

You can get Dapper to make your query, add any parameters, open your connection, download your data, fill up a list full of your classes, close the connection and return it.. all in one line of code:您可以让 Dapper 进行查询、添加任何参数、打开连接、下载数据、填写一个完整的类列表、关闭连接并返回它......全部在一行代码中:

//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

The short short version is: your c# class properties should be named the same as your columns.简短的简短版本是:您的 c# class 属性的名称应与您的列相同。 If they aren't, it's easiest to use AS xyz in the SQL to equalize the names.如果不是,最简单的方法是使用 SQL 中的AS xyz来均衡名称。 If you want to write a parameterized query, you provide @parameterNames that are the same as the property names of an anonymous object you pass at the same time as your query:如果要编写参数化查询,请提供与查询同时传递的匿名 object 的属性名称相同的@parameterNames

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

If you like writing SQL and having that low level control/don't want to use an ORM like EF, then Dapper lets you carry on doing the SQL directly as you're doing, but takes away all the repetitive surrounding boilerplate如果您喜欢编写 SQL 并且具有低级别控制/不想使用 ORM 像 EF,那么 Dapper 可以让您继续执行 Z9778840A0100CB30C98222 周围的所有重复作为样板,但会带走所有重复的

The SQLDataReader class exposes a set of instance methods that allow to retrieve the value of a field of a specific type, such as GetInt32() and GetString() , which can be used in combination with the GetOrdinal() method SQLDataReader class 公开了一组实例方法,这些方法允许检索特定类型的字段的值,例如GetInt32()GetString() ,它们可以与GetOrdinal()方法结合使用

Example例子

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM