Reading data from reader in C# with Sql Server - c#

In C#, which one is more efficient way of reading reader object, through integer indexes or through named indexes ?
ad.Name = reader.GetString(0);
OR
ad.Name = reader["Name"].ToString();

The name overload needs to find the index first.
MSDN
a case-sensitive lookup is performed first. If it fails, a second
case-insensitive search is made (a case-insensitive comparison is done
using the database collation). Unexpected results can occur when
comparisons are affected by culture-specific casing rules. For
example, in Turkish, the following example yields the wrong results
because the file system in Turkish does not use linguistic casing
rules for the letter 'i' in "file".
From Getordinal (which is used therefore):
Because ordinal-based lookups are more efficient than named lookups,
it is inefficient to call GetOrdinal within a loop. Save time by
calling GetOrdinal once and assigning the results to an integer
variable for use within the loop.
so in a loop it might be more efficient to lookup the ordinal index once and reuse that in the loop body.
However, the name-lookup is backed by a class that is using a HashTable which is very efficient.

reader.GetString(index);
This will get the row value at that column index as string, The second solution is more ideal because it allows you to get the value at that index in your own prefered type.
Example:-
String name = reader["Name"].ToString();
int age = (int) reader["Age"]

ad.Name = reader["Name"].ToString();
This is most efficient way.
Because although you change database table structure afterwords, there will be no effect on this code since you have directly mentioned column name.
But with column index, it will change when you add any column to table before this column.

Related

Get value of first column without knowing name

Similar to Column Number rather than Column Name but I believe it's different because that was for unnamed columns, whereas my columns are named, I just don't know the names ahead of time.
First, some background. I'm creating a method that takes a query and its arguments as parameters, then runs the query (using Dapper) and checks if the first row, first column value is a 1 or a 0. It's intended to work as a generic validator for databases.
For example, the user could enter a query that returns a 1 in the only row's only column if some value exists in some table, and a 0 otherwise. The use of this method is intentionally very broad and most of the effort is put on the user writing the query (I should also clarify that the "user" in this case is always another developer and the use is done within code calling this method, not on, say, form input).
I want to query my database and get the value of the first row, first column without knowing the name of the column ahead of time. Ideally (though I'm not sure if this is possible or not within the Dapper call), I'd also like to require that there only be one row and one column in the result. When I was searching around, I based my initial solution on this post's first answer, but found that for that to work I needed to know the name of the column:
var dict = connection.Query(query, parameters).ToDictionary(row => (string)row.VALUE);
if(dict.ElementAt(0).Value != 1){
//do stuff
}
I thought of just adding a requirement that the user add an alias that names the first column some constant value (in this case, VALUE), but I'd prefer not to put the burden on my user if at all possible.
Ultimately my core issue is: how can I get the value of a named column in a DB using Dapper without knowing the name of the column?
Does anybody have any ideas?
I've done this successfully by just using int as the type in the generic Query method as such:
int value = conn.Query<int>(sql,
commandType: CommandType.StoredProcedure).FirstOrDefault();
Notice the use of the FirstOrDefault method. So you get 0 or whatever the value is from the DB.
The easiest thing to do would be to make sure the SQL command ALWAYS returns the same column name, by way of an alias. Then your C# code can just use that alias.
Using Tortuga Chain
var result = DataSource.Sql(query, parameters).ToInt32().Execute();
I'd also like to require that there only be one row and one column in the result
By default, Chain uses DbCommand.ExecuteScalar. This returns the first column of the first row, ignoring everything else. To add that restriction I would do this:
var result = DataSource.Sql(query, parameters).ToInt32List().Execute().Single;
Another option is to change how you generate the SQL. For example,
var filterObject = new {ColumnA = 1, ColumnB = "X", ColumnC = 17};
var result = DataSource.From(tableName, filterObject).ToInt32(columnName).Execute();
This has the advantage of being immune to SQL inject attacks (which is probably a concern for you) and ensures that you SQL only returns one column before it is executed.

Get data from column by using column name?

I iterate a DataTable's rows using -
DataTable dt = getDataTableFromSomeWhere();
DataRow row = null;
//for loop
row = dt.Rows[i];
How do I get the value of a column of the i-th row, by using the name of the column ?
I can iterate the columns using dt.Columns[j], but thats not what I want.
Just use the indexer taking a string parameter:
object value = row["ColumnName"];
EDIT: Assuming the value has been fetched in an appropriate type, I'd normally just cast to the CLR type you want:
int someIntegerValue = (int) row["ColumnName"];
Sometimes you may need two levels of casting (one to unbox and then another to perform an actual value conversion) but it depends on what you need.
I would recommend against converting to a string representation and then parsing that, unless you've really got no alternative. Excessive string conversions not only harm performance (usually not relevant) but they lead to sloppy type choices.
string name = (string) row["ColumnName"];
or
int i = Convert.ToInt32( row["ColumnName"]);
referencing by name is tiny bit slower but way more readable.

ExecuteReader.HasRows vs ExecuteScalar() is DBNull

In an area of my site, I need to control access to a specific set of users.
This is done by checking the user's ID against a table on a SQL server database. If the ID exists then they are granted access:
SELECT 1 FROM admin WHERE userID = #userID
I notice that there are a couple of ways in which I can check for the presence of a row within the database and was wondering if there was any benefit of using either one, or if there was a standard.
The first is by checking for the existence of rows in the SqlDataReader:
if (!SqlCommand.ExecuteReader().HasRows)
{
//redirect
}
The second is to check if the returned value is DBNull using ExecuteScalar():
if (SqlCommand.ExecuteScalar() is DBNull)
{
//redirect
}
Which should I use? Is there a better way? Does it really matter?
The second option because you have less overhead.
However please note
ExecuteScalar returns an object that is
The first column of the first row in the result set, or a null
reference (Nothing in Visual Basic) if the result set is empty
Your query may not return anything, so it is better to check for null instead of DBNull
if (SqlCommand.ExecuteScalar() == null)
{
//redirect
}
Both are same in terms of the performance.
ExecuteScalar only returns the first value from the first row of the dataset. Internal it is treated just like ExecuteReader(), a DataReader is opened, the value is picked and the DataReader gets destroyed afterwards.I also always wondered about that behavior, but it has one advantage: It takes place within the Framework...and you can't compete with the Framework in manners of speed.
Following are the difference between those two:
ExecuteReader():
1.will work with Action and Non-Action Queries (Select)
2.Returns the collection of rows selected by the Query.
3.Return type is DataReader.
4.Return value is compulsory and should be assigned to an another object DataReader.
ExecuteScalar():
1.will work with Non-Action Queries that contain aggregate functions.
2.Return the first row and first column value of the query result.
3.Return type is object.
4.Return value is compulsory and should be assigned to a variable of required type.
taken from
http://nareshkamuni.blogspot.in/2012/05/what-is-difference-between.html
in your case it will not affect much performance so either of them you can use .
ExecuteScalar is typically used when your query returns a single value. If it returns more, then the result is the first column of the first row. An example might be SELECT ##IDENTITY AS 'Identity'.
ExecuteReader is used for any result set with multiple rows/columns (e.g., SELECT col1, col2 from sometable).
SOURCE

SqlDataReader are these two the same Which one is faster

I am working with SqlXml and the stored procedure that returns a xml rather than raw data. How does one actually read the data when returned is a xml and does not know about the column names. I used the below versions and have heard getting data from SqlDataReader through ordinal is faster than through column name. Please advice on which is best and with a valid reason or proof
sqlDataReaderInstance.GetString(0);
sqlDataReaderInstance[0];
and have heard getting data from SqlDataReader through ordinal is faster than through column name
Both your examples are getting data through the index (ordinal), not the column name:
Getting data through the column name:
while(reader.Read())
{
...
var value = reader["MyColumnName"];
...
}
is potentially slower than getting data through the index:
int myColumnIndex = reader.GetOrdinal("MyColumnName");
while(reader.Read())
{
...
var value = reader[myColumnIndex];
...
}
because the first example must repeatedly find the index corresponding to "MyColumnName". If you have a very large number of rows, the difference might even be noticeable.
In most situations the difference won't be noticeable, so favour readability.
UPDATE
If you are really concerned about performance, an alternative to using ordinals is to use the DbEnumerator class as follows:
foreach(IDataRecord record in new DbEnumerator(reader))
{
...
var value = record["MyColumnName"];
...
}
The DbEnumerator class reads the schema once, and maintains an internal HashTable that maps column names to ordinals, which can improve performance.
Compared to the speed of getting data from disk both will be effectively as fast as each other.
The two calls aren't equivalent: the version with an indexer returns an object, whereas GetString() converts the object to a string, throwing an exception if this isn't possible (i.e. the column is DBNull).
So although GetString() might be slightly slower, you'll be casting to a string anyway when you use it.
Given all the above I'd use GetString().
Indexer method is faster because it returns data in native format and uses ordinal.
Have a look at these threads:
Maximize Performance with SqlDataReader
.NET SqlDataReader Item[] vs. GetString(GetOrdinal())?

C# and Pervasive, find the type of data in a column

I am using Pervasive and I would like to know what kind of data a column contains. However, the only overload of PsqlDataReader.GetFieldType accepts an int index. But I want to know using the column name. I guess I could just loop through all the columns and find the one with the specified name, but I do not want to do that.
Is there any way to find the data type of a column by a given column name?
You have to pair the use of GetFieldType with GetOrdinal (which returns the int index of the column):
PsqlDataReader.GetFieldType(PsqlDataReader.GetOrdinal("ColumnName"));
I am not sure, but try use it like this
SqlDataReader.GetFieldType["ColumnName"];

Categories

Resources