SqlCommand with more than one result table - c#

I'm working on an ASP.NET Web Application with Visual Studio 2010. My target framework is ".NET Framework 4" and I'm sending queries to a SQL Server 2008 database which version is "Microsoft SQL Server 2008 R2 (SP2)".
I'm connecting using the following connection string "Data Source=XXXX;Initial Catalog=XXXX;Integrated Security=False;User Id=XXXX;Password= XXXX;MultipleActiveResultSets=True" and sending queries with the code below:
public static List<DataTable> getData(String query)
{
var results = new List<DataTable>();
try
{
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
command.CommandTimeout = 0;
using (SqlDataReader reader = command.executeReader())
{
do
{
while (reader.Read()) ;
var dataTable = new DataTable();
dataTable.Load(reader);
results.Add(dataTable);
} while (reader.NextResult());
}
connection.Close();
}
}
}
}
The query I'm sending is an Stored Procedure which returns two tables, at first it had a loop which calls another Stored Procedure depending on some internal condition, creation and insertion on a tempdb..#table and two SELECT statements.
But now it only contains:
SELECT 1,2,3,4,5
SELECT 6,7,8,9,0
I don't know why but the reader.NextResult() is always false so I never get the second table result.
Does anyone know what I'm doing wrong? What should I do to receive and read the two results from the query?

if this is using a stored proc you need something like this: notice the command type
using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(myConnString))
{
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand())
{
cmd.CommandText = "myMultipleTablesSP";
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter(cmd);
DataSet ds = new DataSet();
adapter.Fill(ds);
conn.Close();
}
}
if for example you return 2 tables in your SP, like:
SELECT * FROM [TableA];
SELECT * FROM [TableB];
you would access this tables as:
DataTable tableA = ds.Tables[0];
DataTable tableB = ds.Tables[1];

OK, I have run some test and find out the problem is from dataTable.Load(reader); somehow and I don't know why and what is exactly happening behind that method.
but if you use
do {
while(reader.Read()) {
...
}
} while (reader.NextResult());
everything works as expected.

Related

Why does my MySQL connection not work in visual studio code C#?

i am making a program in visual studio code with C#, it is a paid program so it needs an hwid system. Basically i want it to check if your computer HWID exists in the HWID table in my users database. But it says it can't connect to the database. Can you help me? This is my code.`
string connectionString = "Server=SomeServer;Database=i got you this is notthe real database;User ID=same;Password=same for password;";
MySqlConnection mydbCon = new MySqlConnection(connectionString);
mydbCon.Open();
MySqlCommand command = mydbCon.CreateCommand();
command.CommandText = "SELECT * FROM yourTable WHERE hwid = GetHDDSerial";
IDataReader reader = command.ExecuteReader();
`
It could be that the connection string isn't formatted the way the MySQL connector wants it. The MySQL documentation shows "uid" instead of User, and "pwd" instead of Password. https://dev.mysql.com/doc/connector-net/en/connector-net-programming-connecting-connection-string.html
This should do what you need:
string connectionString = "Server=SomeServer;Database=i got you this is notthe real database;User ID=same;Password=same for password;";
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
using (MySqlCommand command = new MySqlCommand())
{
string sql = "SELECT * FROM yourTable WHERE hwid = #val1";
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = sql;
command.Parameters.AddWithValue("#val1", "GetHDDSerial");
connection.Open();
using (MySqlDataAdapter adapter = new MySqlDataAdapter())
{
using (DataSet ds = new DataSet())
{
adapter.SelectCommand = command;
adapter.Fill(ds);
if (ds.Tables.Count > 0)
{
DataTable dt = ds.Tables[0];
foreach (DataRow row in dt.Rows)
{
// Do something here. You can access the data like this:
// row["Id"] or whatever your field names are.
// int id = (int) row["Id"];
// Of course, I don't know your field names, so you'll have to complete this.
}
}
}
}
}
}

SQL Performance Issue ASP.Net App

We have a performance Issue in our ASP.NET based web App and it's visible only once when we login in the morning. As per Log looks like below query takes more than 1 minute 20 secs. Next time onward when user login to the app and try to access same page doesn't find any issue. Can you please let me know how to optimize this query ? Any thoughts how we can fix this problem ?
Log -
"11/13/15","08:38:27","ExecuteSql - ---3---- ","8",""
"11/13/15","08:38:27","ExecuteSql - ---4---- : SQL : SELECT TOP 1 CONVERT(varchar(15), Period_End_Date, 107) as PDate FROM PBHISTORY..STATEMENT_OF_CHANGE
ORDER BY Period_End_Date DESC","8",""
"11/13/15","08:39:48","ExecuteSql - ---5---- ","8",""
SQL :
SELECT TOP 1
CONVERT(varchar(15), Period_End_Date, 107) as PDate
FROM
PBHISTORY..STATEMENT_OF_CHANGE
ORDER BY
Period_End_Date DESC
C# ASP.NET -
public string GetDateRangeReportingDate(int reportId)
{
var report = GetReportInfoById(reportId);
string sql = string.Format(#"SELECT TOP 1 CONVERT(varchar(15), Period_End_Date, 107) as PDate FROM {0}..{1} ORDER BY Period_End_Date DESC", _historyDatabase, report.SourceTableName);
var data = ExecuteSql(sql);
while (data.Read())
{
return data["PDate"].ToString();
}
return null;
}
private SqlDataReader ExecuteSql(string sql)
{
SqlDataReader reader;
SqlConnection conn;
var commandTimeOut = ConfigurationManager.AppSettings["PBReportCommandTimeout"].ToString();
string connString = ConfigurationManager.ConnectionStrings["PBReportCS"].ConnectionString;
conn = new SqlConnection(connString);
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandTimeout = int.Parse(commandTimeOut);
reader = cmd.ExecuteReader();
return reader;
}
I found solution of my performance issue I mentioned above. Issue was wrong indexing in table and I fixed this issue by changing the indexing of table where from we are fetching records in production.
Also, I fixed Framework level entity class by using SQL Data Adapter and using statements. App runs super fast in production. Thanks for your help.
private string ExecuteSqlNew(string sql)
{
string connectionString = ConfigurationManager.ConnectionStrings["PBReportCS"].ConnectionString;
string commandTimeOut = ConfigurationManager.AppSettings["PBReportCommandTimeout"].ToString();
DataSet result = new DataSet();
string pDate = "";
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
conn.Open();
cmd.CommandTimeout = int.Parse(commandTimeOut);
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
adapter.Fill(result);
adapter.Dispose();
conn.Close();
pDate = result.Tables[0].Rows[0]["PDate"].ToString();
}
}
}
catch(Exception ex)
{
throw ex;
}
return pDate;
}

How do I retrieve the values of a single column from a database table?

I have a table where I am trying to capture all the values in one column across many rows with a matching identifier. For example my query is similar to:
SELECT
prevHours
FROM
submissions
WHERE
projectCat='Capacity'
I am then trying to pass all of the values in prevHours into a single array that I can perform operations on.
The simplest way to work with a list of values from the database is to use a List<T>; the code is similar to what you have now, see below.
The code is quite simple:
var container = new List<int>();
var dbConnection = "...";
var query = "SELECT [prevHours] FROM [submissions] WHERE [projCat] = #Value";
using(var connection = new SqlConnection(dbConnection))
using(var command = new SqlCommand(query, connection))
{
connection.Open();
command.Parameters.Add("#Value", SqlDbType.VarChar, max).Value = "Capacity";
using(var reader = command.ExecuteReader())
while(reader.Read())
{
if(reader["prevHours"] != DBNull.Value)
container.Add(Convert.ToInt32(reader["prevHours"]));
}
}
Additionally, if you are not using the list for further processing, you could use ExecuteScalar and a query of the form
SELECT SUM(prevHours) FROM submissions WHERE projCat = #Value
for similar results using command.ExecuteScalar()
I write a function to return a database table:
public static DataTable ExecuteDataTable(SqlConnection conn, string cmdText,
params SqlParameter[] parameters)
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = cmdText;
cmd.Parameters.AddRange(parameters);
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
adapter.Fill(dt);
return dt;
}
}
}`

How to parameterise table name in ODBC query

I have an ODBC connection to a database and I would like the user to be able to view data within any table. As this is an ASP.net application I cannot trust that the table name sent doesn't also contain nasties. I have tried using a parameterised query but I always get an error saying that I "Must declare the table variable" - this appears to be an issue because it is the table name
string sql = "SELECT TOP 10 * FROM ? ";
OdbcCommand command = new OdbcCommand(sql, dbConnection);
command.Parameters.Add(new OdbcParameter("#table", tableName));
OdbcDataAdapter adapter = new OdbcDataAdapter();
adapter.SelectCommand = command;
adapter.Fill(tableData);
What is the best method to achieve this in a secure way?
Use a stored procedure, it's the safest way.
Some hints:
You probably may also use the System.Data.SqlClient namespace objects
Enclose your connection, command and adapter objects initializations in using statements
Here's a simple example:
string sqlStoredProcedure = "SelectFromTable";
using (OdbcConnection dbConnection = new OdbcConnection(dbConnectionString))
{
dbConnection.Open();
using (OdbcCommand command = new OdbcCommand(sqlStoredProcedure, dbConnection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Add(new OdbcParameter("#table", tableName));
using (OdbcDataAdapter adapter = new OdbcDataAdapter(command))
{
adapter.SelectCommand = command;
adapter.Fill(tableData);
}
}
}
Another way to go would be to retrieve all table names and validate the tableName string variable as an entry in the list, maybe using:
DataTable tables = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables);
Here's a simple implementation based on your scenario:
string sql = "SELECT TOP 10 * FROM {0}";
using (OdbcConnection dbConnection = new OdbcConnection(dbConnectionString))
{
dbConnection.Open();
DataTable tables = dbConnection.GetSchema(OdbcMetaDataCollectionNames.Tables);
var matches = tables.Select(String.Format("TABLE_NAME = '{0}'", tableName));
//check if table exists
if (matches.Count() > 0)
{
using (OdbcCommand command = new OdbcCommand(String.Format(sql, tableName), dbConnection))
{
using (OdbcDataAdapter adapter = new OdbcDataAdapter(command))
{
adapter.SelectCommand = command;
adapter.Fill(tableData);
}
}
}
else
{
//handle invalid value
}
}

Simple SQL select in C#?

On my current project, to get a single value (select column from table where id=val), the previous programmer goes through using a datarow, datatable and an sqldatadapter (and of course sqlconnection) just to get that one value.
Is there an easier way to make a simple select query? In php, I can just use mysql_query and then mysql_result and I'm done.
It would be nice if I could just do:
SqlConnection conSql = new SqlConnection(ConnStr);
SomeSqlClass obj = new SomeSqlClass(sql_string, conSql);
conSql.Close();
return obj[0];
Thanks for any tips.
You can skip the DataReader and the DataAdapter and just call ExecuteScalar() on the sql command.
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand("SELECT * FROM whatever
WHERE id = 5", conn);
try
{
conn.Open();
newID = (int)cmd.ExecuteScalar();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
You are probably looking for SqlCommand and SqlDataReader
Dictionary<int, string> users = new Dictionary<int, string>();
using(SqlConnection connection = new SqlConnection("Your connection string"))
{
string query = "SELECT UserId, UserName FROM Users";
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
users.Add(reader.GetInt32(0), reader.GetString(1));
}
connection.Close();
}
Actually, there is a method SqlCommand.ExecuteScalar() that will simply return the first field from the first row of the returned results. Just for you.
.NET Framework Class Library
SqlCommand..::.ExecuteScalar Method
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.
You can do something very similar:
using (SqlConnection conn = new SqlConnection(ConnStr))
using (SqlCommand cmd = new SqlCommand(sql_string, conn))
{
conn.Open();
return cmd.ExecuteScalar();
}
you can use SqlCommands executeScalar function. Please look at the following link
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx

Categories

Resources