Most of my queries are very short, 1-3 records total. This is the code I have now. I am wondering if there is a way to capture userid directly from DataAdapter without going through a table. Thanks!
SqlDataAdapter dataAdapter = new SqlDataAdapter(strSQL, strCon);
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
DataTable t = new DataTable();
dataAdapter.Fill(t);
int userid = 0;
if (t.Rows.Count > 0)
{
DataRow dr = t.Rows[0];
userid = dr.Field<int>(0);
If you have only one return value, you can use ExecuteScalar and you have ExecuteReader to get multiple return values.
Here's the msdn sample:
private static void CreateCommand(string queryString,
string connectionString)
{
using (SqlConnection connection = new SqlConnection(
connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(String.Format("{0}", reader[0]));
}
}
}
Use a reader:
http://msdn.microsoft.com/en-US/library/system.data.sqlclient.sqldatareader(v=vs.80).aspx
Quicker and less resources 1 record or hundreds.
Related
I have a datatable with required data.
try
{
using (var connection = conn)
{
using (var command = conn.CreateCommand())
{
command.CommandText = SqlCommand;
command.CommandType = CommandType.Text;
if (connection.State == ConnectionState.Closed)
connection.Open();
command.Connection = connection;
DbDataReader reader = command.ExecuteReader();
var dataTable = new DataTable();
dataTable.Load(reader);
if (dataTable.Rows.Count > 0)
{
}
Datatable has columns from joins.
comments, commnets1, comments2, , ...comments17.
Updateby, Updateby1, updatedby2, ...updatedby17
updateddate,updateddate1, updateddate2, ...updateddate17
So I need to find only the columns tat starts with "abc" and check if they are not null. How can I do this any suggestions ? Thanks for your help. I was thinking if we can create another data table with just those columns and check each column is not empty
I have the following:
String sql = "SELECT * FROM Temp WHERE Temp.collection = '" + Program.collection + "'";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(sql, conn);
Program.defaultCollection = (String)cmd.ExecuteScalar();
And I want to get the second column after executing the statement. I know it will return only one row with two columns
I have read online that I will have to read each row of the result, is there any other way?
ExecuteScalar gets the first column from the first row of the result set. If you need access to more than that you'll need to take a different approach. Like this:
DataTable dt = new DataTable();
SqlDataAdapater sda = new SqlDataAdapter(sql, conn);
sda.Fill(dt);
Program.defaultCollection = dt.Rows[0]["defaultCollection"];
Now, I realize that the field name may not be defaultCollection, but you can fill that in.
From the MSDN documentation for ExecuteScalar:
Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
Now, as a final bit of advice, please wrap all ADO.NET objects in a using statement. Like this:
using (SqlConnection conn = new SqlConnection(connString))
using (SqlDataAdapter sda = new SqlDataAdapter(sql, conn))
{
DataTable dt = new DataTable();
sda.Fill(dt);
// do something with `dt`
}
this will ensure they are properly disposed.
And I want to get the second column after executing the statement
It is not possible with execute scalar.
is there any other way
You have 2 options here either to use SqlDataAdapter or SqlDataReader.
For you using DataReader is a recommended approach as you don't need offline data or do other worh
by using SqlDataAdapter
using (SqlConnection c = new SqlConnection(
youconnectionstring))
{
c.Open();
/
using (SqlDataAdapter a = new SqlDataAdapter(sql, c))
{
DataTable t = new DataTable();
a.Fill(t);
if(t.Rows.Count > 0)
{
string text = t.Rows[0]["yourColumn"].ToString();
}
}
}
by using DataREader
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(sql, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
//read data here
string text = reader.GetString(1)
}
reader.Close();
}
SqlCommand.ExecuteScalar() can be used only when the result have just one row and one column.
If you need more than one column to be returned, you should use something like this:
String sql = "SELECT * FROM Temp WHERE Temp.collection = '" + Program.collection + "'";
SqlConnection conn = new SqlConnection(connString);
using(SqlCommand cmd = new SqlCommand(sql, conn))
{
using(SqlDataReader rdr = cmd.ExecuteReader())
{
if(rdr.Read())
{
Program.defaultCollection = (String)rdr["Column1"];
Program.someOtherVar = (String)rdr["Column2"];
}
}
rdr.Close();
}
That will be the fastest way.
You can use a DataReader and read only the first column like:
IDataReader cReader = cmd.ExecuteReader();
if(cReader.Read())
{
string cText = cReader.GetString(1); // Second Column
}
ExecuteScalar only returns one value. You have to make sure your query only returns that value.
String sql = "SELECT temp.defaultCollection FROM Temp WHERE Temp.collection = '" + Program.collection + "'";
On a side note, read on SqlParameter. You don't want to concatenate values like that, you'll have a problem when the collection property contains a quote.
What is the code with the smallest number of lines that will generate a DataTable from this SQL query?
SELECT *
FROM [Table1]
WHERE ([Date] BETWEEN #Date1 AND #Date2) AND
([Field1] IS NULL OR [Field2] IS NULL)
Use SqlDataAdapter to fill a DataTable.
DataTable dt = new DataTable();
using (SqlConnection yourConnection = new SqlConnection("connectionstring"))
{
using (SqlCommand cmd = new SqlCommand("....your sql statement", yourConnection))
{
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
Use using block with your SqlConnection, SqlCommand and SqlDataAdapter since they implement IDisposable interface. Also use Parameterized query
Try this
SqlCommand command = new SqlCommand(query, conn);
DataTable dt = new DataTable();
using(SqlDataReader reader = command.ExecuteReader())
{
dt.Load(reader);
}
SqlDataAdaptor and FillSchema
It will create your table on the fly
Applied On a DataSet
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldataadapter.aspx
Applied On a DataTable
http://msdn.microsoft.com/en-us/library/152bda9x.aspx
string query = "select * from cfo_daily_trans_hist";
try
{
using (SqlConnection connection = new SqlConnection(
cnnString))
{
SqlCommand command = new SqlCommand(query);
command.Connection = connection;
connection.Open();
var result = command.ExecuteReader();
DataTable datatable = new DataTable();
datatable.Load(result);
connection.Close();
}
}
So the var result is created through the ExecuteReader(); and HasRows is true, and it shows the correct amount of fields. However, the DataTable that I create from it is empty.
What am I doing wrong? I'm 99% sure it's getting data, but I don't know how to find it through the SqlDataReader object to make sure.
Thanks.
Instead of a SqlDataReader, use a SqlDataAdapter.
SqlDataAdapter myAdapter = new SqlDataAdapter(command);
myAdapter.Fill(datatable);
With a SqlDataAdapter, you don't need to explicitly call SqlConnection.Open() and SqlConnection.Close(). It is handled in the Fill() method.
You can try to add "COALESCE" in your sql command statement ... if you have some NULL value in your query result, you will have problem with dataTable
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
// Call Close when done reading.
reader.Close();
}
}
How can I enhance the method above to accept any queryString? The problem is in the while. There's a fixed # of columns I can read. I want to be able to read any number of columns so that I can populate and return a DataSet. How can I do it?
You can do something along these lines:
private static void ReadOrderData(string connectionString,
string query, Action<SqlDataReader> action)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command =
new SqlCommand(query, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
action(reader);
}
// Call Close when done reading.
reader.Close();
}
}
You're really barking up the wrong tree. You shouldn't be using "methods that accept query strings". You should raise the level of abstraction by using Entity Framework or the like.
You will then not need to use the above code because it will not exist. Those who would have called that code will do something like this:
var orders = from o in ordersDAL.Orders
select new {o.OrderID, o.CustomerID};
foreach (var order in orders)
{
Console.WriteLine("{0}, {1}", order.OrderID, order.CustomerID);
}
Your code is badly designed in any case. Why in the world would you combine the fetching of the data with the use of it? That while loop should not be in that same method.
I would use something like the answer from obrok, but I would add the ability to use parameters.
Also, the SqlCommand and SqlDataReader both need to be within a using block:
private static void ReadOrderData(string connectionString,
string query, Action<SqlDataReader> action)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command =
new SqlCommand(query, connection)) {
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()) {
// Call Read before accessing data.
while (reader.Read())
{
action(reader);
}
// No need to call Close when done reading.
// reader.Close();
} // End SqlDataReader
} // End SqlCommand
}
}
Use SqlDataAdapter:
private static DataSet ReadData(string connectionString, string queryString)
{
DataSet dataSet;
using (SqlConnection connection =
new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command =
new SqlCommand(queryString, connection);
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(dataSet);
}
return dataSet;
}
Or something like this.
How I'm doing this:
(basically idea is to use DataSet along with IDataAdapter)
DataSet ds = null;
List<SqlParameter> spParams = ...
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(spName, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Clear();
command.Parameters.AddRange(spParams);
connection.Open();
IDbDataAdapter da = new SqlDataAdapter();
da.SelectCommand = command;
ds = new DataSet("rawData");
da.Fill(ds);
ds.Tables[0].TableName = "row";
foreach (DataColumn c in ds.Tables[0].Columns)
{
c.ColumnMapping = MappingType.Attribute;
}
}
}
// here is you have DataSet flled in by data so could delegate processing up to the particular DAL client
You said you tried EF, but did you try Dapper ? looks like a simple enough ORM that should work with your database (it's raw SQL), and will avoid you most of this mapping code. Dapper is used in StackOverflow so it cannot be too bad :)
Same suggestion as 'WorkerThread' but change the Method Signature to:
private static DataSet ReadOrderData(string connectionString, string queryString)
{
// do work
}
Drop the following line from 'WorkerThread' example:
string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";
Once you have made these two changes to 'WorkerThread's' method it should be perfect for what you need.
Look at the DataTable.Load method. Or, for a finer level of control, check out the properties and methods on IDataReader, such as FieldCount, GetFieldType, and GetName.