ExecuteReader.HasRows vs ExecuteScalar() is DBNull - c#

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

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.

Reading data from reader in C# with Sql Server

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.

Can I access entire DataTable if all I have is a single DataRow?

DataRow contains a Table property, which seems to return the entire Table for which this row belongs.
I'd like to know if I can use that table safely, or if there are gotcha's.
In http://msdn.microsoft.com/en-us/library/system.data.datarow.table.aspx documentation, it says "A DataRow does not necessarily belong to any table's collection of rows. This behavior occurs when the DataRow has been created but not added to the DataRowCollection.", but I know for a fact my row belongs to a table.
In terms of pointers, if each Row from DataTable points to original DataTable, than I'm good to go. Is that all 'Table' property does?
Just to explain why I'm trying to get entire Table based on a single DataRow:
I'm using linq to join two (sometimes more) tables. I'd like to have a generic routine which takes the output of linq (var), and generate a single DataTable with all results.
I had opened another question at stackoverflow (Join in LINQ that avoids explicitly naming properties in "new {}"?), but so far there doesn't seem to be a generic solution, so I'm trying to write one.
if you know the row is part of table than yes you can access it without any problem. if the possibility exists where the row may not be associated to a table than check if the property is null.
if(row.Table == null)
{
}
else
{
}
As long as it's not null, you can use it freely.

How to get Indentity value back after insert

Given the following code (which is mostly irrelevant except for the last two lines), what would your method be to get the value of the identity field for the new record that was just created? Would you make a second call to the database to retrieve it based on the primary key of the object (which could be problematic if there's not one), or based on the last inserted record (which could be problematic with multithreaded apps) or is there maybe a more clever way to get the new value back at the same time you are making the insert?
Seems like there should be a way to get an Identity back based on the insert operation that was just made rather than having to query for it based on other means.
public void Insert(O obj)
{
var sqlCmd = new SqlCommand() { Connection = con.Conn };
var sqlParams = new SqlParameters(sqlCmd.Parameters, obj);
var props = obj.Properties.Where(o => !o.IsIdentity);
InsertQuery qry = new InsertQuery(this.TableAlias);
qry.FieldValuePairs = props.Select(o => new SqlValuePair(o.Alias, sqlParams.Add(o))).ToList();
sqlCmd.CommandText = qry.ToString();
sqlCmd.ExecuteNonQuery();
}
EDIT: While this question isn't a duplicate in the strictest manner, it's almost identical to this one which has some really good answers: Best way to get identity of inserted row?
It strongly depends on your database server. For example for Microsoft SQL Server you can get the value of the ##IDENTITY variable, that contains the last identity value assigned.
To prevent race conditions you must keep the insert query and the variable read inside a transaction.
Another solution could be to create a stored procedure for every type of insert you have to do and make it return the identity value and accept the insert arguments.
Otherwise, inside a transaction you can implement whatever ID assignment logic you want and be preserved from concurrency problems.
Afaik there is not finished way.
I solved by using client generated ids (guid) so that my method generated the id and returns it to the caller.
Perhaps you can analyse some SqlServer systables in order to see what has last changed. But you would get concurrency issues (What if someone else inserts a very similar record).
So I would recommend a strategy change and generate the id's on the clients
You can take a look at : this link.
I may add that to avoid the fact that multiple rows can exist, you can use "Transactions", make the Insert and the select methods in the same transaction.
Good luck.
The proper approach is to learn sql.
You can do a SQL command followed by a SELECT in one run, so you can go in and return the assigned identity.
See

strongly typed dataset and custom executescalr queries returning values

I have a strongly typed dataset, i must return some scalar values : the sum of values of column, the count of records with a specified column value and so on.
I' have added some custom queries to the dataset of the kind : select sum(mycolumn) as itsname from thetable [where anothercolumn = :myparameter] (last part is optional and i'm using oracle).
I've found that some queries return generics (i.e decimal? ) while other return object. I haven't found a rule for it, some get parameters others don't.
Does anybody knows why i get this different behaviour ?
Now i'm handling every query as if it where returning object, but i'd like to know if i'm doing somenthig wrong or what's the reason of this annoying behaviour
The type of value that is computed in database query will depend upon the database (it will decide that based upon type of operands and operation). For example, if the database computes the result as say currency then corresponding .NET value will be Decimal and so on. You can use database casting/type conversion operation in the query itself to ensure particular return type for the expression.

Categories

Resources