I'm trying to use DDTek Ado.Net library for a Sybase Server in C# to find a query's show plan.
I was wondering if anyone knew how Sybase DDtek library can be used to do this. Here's some sample code of what I've tried before:
using (SybaseConnection dbConnect = new SybaseConnection())
{
dbConnect.ConnectionString = ConfigurationManager.ConnectionStrings["SybaseDB"].ConnectionString;
dbConnect.StatisticsEnabled = true;
dbConnect.Open();
dbConnect.InfoMessage += OnInfoMessage;
SybaseCommand cmd = new SybaseCommand { CommandTimeout = 1000, Connection = dbConnect };
SybaseCommand cmd2 = new SybaseCommand { CommandTimeout = 1000, Connection = dbConnect };
cmd.CommandText = "SET SHOWPLAN ON";
// int ans = cmd.ExecuteNonQuery();
cmd2.CommandText = mainSql;
SybaseDataReader sDR = cmd2.ExecuteReader();
// var ansp = cmd2.ExecuteNonQuery();
//ans = cmd.ExecuteNonQuery();
String plan = String.Empty;
//sql.ToString();
var stats1 = dbConnect.RetrieveStatistics();
//var ans = cmd.ExecuteScalar();
var stats2 = dbConnect.RetrieveStatistics();
//.ExecuteNonQuery(); // no value needed in return
//cmd.CommandText = "SET SHOWPLAN OFF";
//cmd.ExecuteNonQuery();
dbConnect.Close();
dbConnect.Dispose();
}
Where the mainSql Variable is a call to a stored procedure around a select query and having the lines:
set showplan on
--set noexec on
set fmtonly on
When run in RapidSQL, a show plan is generated with no data rows returned. Using debugger to drill into the returned object yielded no show plan info. Perhaps I was looking in the wrong place?
Figured it out. Don't use a stored procedure. Put the select query in mainSql variable. Don't execute with ExecuteReader, execute both Show Plan command and select query with .ExecuteNonQuery.
This triggers the InfoMessage Callback in the Errors object of the SybaseInfoArgs passed into it. These can be concatenated into a message similar to what you getin RapidSql.
Related
Scenario
I'm working with SQL Server 2017 (not possible to change)
I'm using Visual Studio 2019 in C# console and .NET Framework 4.5 (possible to change)
I'm using ADO.NET because several years before we couldn't use Entity Framework, as the system is made to work with a stored procedure that returns at least 100k rows (possible to change)
Situation
I have an USP that returns a table that is at least 100k of rows by 20 fields. I need to add an output parameter in order to get also an ID created by the USP itself. So, the situation is that I need return a table and an ID (called ProcMonitorId). I don't know if this is even so possible (See workarounds section)
At the SQL level is seems to be so far so good:
CREATE PROCEDURE [myschema].[mystore]
#ProcMonitorId BIGINT OUTPUT
AS
BEGIN
BEGIN TRANSACTION
(...)
SELECT fields FROM myTable
SELECT #ProcMonitorId = #internalVariable
SQL execution:
And at repository layer (only relevant lines, someone were surprised for health of example):
var command = new SqlCommand("myStoreProcedure", mycon);
command.CommandType = CommandType.StoredProcedure;
SqlParameter outPutParameter = new SqlParameter();
outPutParameter.ParameterName = "#ProcMonitorId";
outPutParameter.SqlDbType = System.Data.SqlDbType.BigInt;
outPutParameter.Direction = System.Data.ParameterDirection.Output;
command.Parameters.Add(outPutParameter);
// Open connection etc-etc that works
SqlDataAdapter da = new SqlDataAdapter(command);
DataTable dt = new DataTable();
string ProcMonitorId = outPutParameter.Value.ToString();
da.Fill(dt);
Everything worked fine until the addition of the output at C# level. It returns in the line:
string ProcMonitorId = outPutParameter.Value.ToString();
it returns NullReferenceException because Value is null (that can't be) and of course, can't convert to String. I would solve this situation by adding a ? but if that's situation happens for real, I need catch it any way as error. The main idea is that Value can not be null.
As I don't have any ORM map, (and my expertise is not ADO.NET but Entity Framework) I can't understand why is null (No, is not null at SQL layer, always return a value)
Question
How can I solve this error or how can I return a BIGINT parameter and ALSO a table result?
Workarounds
As I first glance I have to solve it quickly, I made a:
SELECT 1 as type, #procID as procid, null as data1, null as data2
UNION ALL
SELECT 2 as type, null as procid, data1, data2
in order to simulate a "header" and "data" rows on one single table.
But I don't like this solution and is not very elegant and flexible. I've to parse the header every time.
Thanks in advance and please comment anything, tip, help, workaround, I will be glade to update my answer if more information is needed.
Also I can make my Framework to .NET Core or change to Entity Framework. That I can't change is my SQL version
Update #2
No changes in SQL - Still working as screenshot
In C# - Hangs out for ever
SqlConnection connection = new SqlConnection(ConfigurationManager.AppSettings["DbConnection"]);
connection.Open();
var command = new SqlCommand("myUSP", connection);
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = Convert.ToInt16(ConfigurationManager.AppSettings["DataBaseTimeOut"]);
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
SqlParameter r = command.Parameters.Add("#ProcMonitorId", SqlDbType.BigInt);
r.Direction = ParameterDirection.Output;
DataTable dt = new DataTable();
using (var rdr = command.ExecuteReader())
{
dt.Load(rdr);
long id = (long)r.Value;
}
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(dt);
The parameter value won't be available until after you consume the resultset, eg
var cmd0 = new SqlCommand("create or alter procedure pFoo #id int output as begin select * from sys.objects; set #id = 12; end", con);
cmd0.ExecuteNonQuery();
var cmd = new SqlCommand("pFoo", con);
cmd.CommandType = CommandType.StoredProcedure;
var p1 = cmd.Parameters.Add("#id", SqlDbType.Int);
p1.Direction = ParameterDirection.Output;
var dt = new DataTable();
using (var rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
var id = (int)p1.Value;
}
You should use a Parameter with the Direction property set to ReturnValue, and, inside the sp, declare an internal variable and set it to the value you want.
Then call the RETURN statement before leaving the StoredProcedure.
As an example, see this SP:
ALTER PROCEDURE [GetTimeZoneGMT]
#TimeZone NVARCHAR(128)
AS
BEGIN
DECLARE #timeZoneNumber as INT = -20;
IF #TimeZone ='Pacific/Midway'
SET #timeZoneNumber = -11
ELSE IF #TimeZone ='Pacific/Niue'
SET #timeZoneNumber = -11
ELSE IF #TimeZone ='Pacific/Pago_Pago'
SET #timeZoneNumber = -11
SELECT 1 -- or whatever you need to have as result set
RETURN #timeZoneNumber;
END
The stored procedure ends with a (bogus) SELECT statement but also has a RETURN statement with the parameter set inside the SP logic.
Now from the C# side you could call it in this way (LinqPad example)
using (var connection = new SqlConnection("Data Source=(LOCAL);Initial Catalog=LinqPADTest;Integrated Security=True;"))
{
connection.Open();
SqlCommand cmd = new SqlCommand("GetTimeZoneGMT", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#TimeZone", SqlDbType.NVarChar).Value = "Asia/Kuala_Lumpur";
SqlParameter r = cmd.Parameters.Add("#p2", SqlDbType.BigInt);
r.Direction = ParameterDirection.ReturnValue;
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
r.Value.Dump(); // Prints -20
dt.Dump(); // Prints a row with a single column with 1 as value
}
I am populating a text box with the returned value of a function, but it doesn't work if I run the sql code inside the function. I can remove the sql related code and it works. so i'm stumped.
And by "doesn't work" i mean that the text box never gets populated with anything. it remains blank.
thanks
public string CreateResident()
{
string result = "hmm";
SqlConnection sqlConnection = new SqlConnection("Server=DELLXPS\\SQLEXPRESS; Initial Catalog=Warren_SEINDATASYSTEMS; Integrated Security=true;");
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO [dbo].[NewUsers]([ResidentAccountNumber],[ResidentName],[ResidentAddress],[NumberOfVisitors],[TempPass],[Role])VALUES(#ResidentAccountNumber,#ResidentName,#ResidentAddress,#NumberOfVisitors,(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
SqlParameter ResidentAccountNumber = new SqlParameter();
ResidentAccountNumber.ParameterName = "#ResidentAccountNumber";
ResidentAccountNumber.Value = txtboxResidenetAccountNumber.Text.Trim();
cmd.Parameters.Add(ResidentAccountNumber);
SqlParameter ResidentName = new SqlParameter();
ResidentName.ParameterName = "#ResidentName";
ResidentName.Value = txtboxResidentName.Text.Trim();
cmd.Parameters.Add(ResidentName);
SqlParameter ResidentAddress = new SqlParameter();
ResidentAddress.ParameterName = "#ResidentAddress";
ResidentAddress.Value = txtboxResidentAddress.Text.Trim();
cmd.Parameters.Add(ResidentAddress);
SqlParameter NumberOfVisitors = new SqlParameter();
NumberOfVisitors.ParameterName = "#NumberofVisitors";
NumberOfVisitors.Value = txtboxNumberOfVisitors.Text.Trim();
cmd.Parameters.Add(NumberOfVisitors);
try
{
sqlConnection.Open();
result = (string)cmd.ExecuteScalar();
sqlConnection.Close();
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
protected void btnCreateResident_Click(object sender, EventArgs e)
{
txtboxTempPassword.Text = CreateResident();
}
Your SQL is wrong and you have a lot of problems but I want to show you a way to make your code more readable. Format it like this:
cmd.CommandText = #"INSERT INTO [dbo].[NewUsers] ([ResidentAccountNumber],[ResidentName],[ResidentAddress], NumberOfVisitors],[TempPass], Role])
VALUES(
#ResidentAccountNumber,
#ResidentName,
#ResidentAddress,
#NumberOfVisitors,
(select cast((Abs(Checksum(NewId()))%10) as varchar(1)) + char(ascii('a')+(Abs(Checksum(NewId()))%25)) + char(ascii('A')+(Abs(Checksum(NewId()))%25)) + left(newid(),5)),
'resident')";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
We know that a select in a VALUES constructor is not legal so that is one problem.
Also having a SELECT without a from seems strange -- did you copy your code correctly?
You are using ExecuteScalar -- do you know what that does? It shouldn't include a query that includes INSERT query.
I'm guessing you probably want a stored procedure.
I would suggest do not write query in C# code, you must use Stored Procedure for the same purpose.
If you want your query to return some id, primary key or some value then you must write query for that after your insert query.
you can use the following keywords in your select query,if you want to return id from table.
SCOPE_IDENTITY returns the last IDENTITY value inserted into an IDENTITY column in the same scope.
IDENT_CURRENT returns the last identity value generated for a specific table in any session and any scope.
##IDENTITY returns the last identity value generated for any table in the current session, across all scopes.
If you want to return only one record then use ExecuteScalar else you can use ExecuteReader.
If your only purpose is to insert data into the table then you should use ExecuteNonQuery.
With the help of comments I went with ExecuteReader instead of the ExecuteScaler. And changed the statement to return a value
INSERT INTO [table] ([fields]) OUTPUT Inserted.MyColumn VALUES(values)
C# Code:
reader = cmd.ExecuteReader();
try
{
while (reader.Read())
{
result = reader[0].ToString();
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
I've spent about 7 hours trying to figure this out by trial and error. All the online examples I have seen either don't work, or dont apply, or only show half of what Im looking for.
Here is what I'm asking for:
1. An example of a simple stored procedure in MYSQL using one IN parameter and one OUT parameter.
2. An example of a FUNCTIONING (really important, cause online examples havent worked sometimes...) call from Visual Studio, using C#. Either a text call or stored procedure command type work.
3. AddWithValue has been deprecated.
4. I would love to see the out parameter actually work.
If this is impossible with MYSQL and visual studio, that would be nice to know as well.
MYSQL documentation is not thorough enough for this particular example. And pls, no Visual Studio or C# hatred.
Thanks in advance! :)
EDIT:
This is what I have managed to do so far, and it DOES NOT WORK!!!
MYSQL side, using HeidiSQL:
CREATE DEFINER=`root`#`localhost` PROCEDURE `login`(IN `stuff` VARCHAR(50), IN `pass` VARCHAR(50), OUT `param3` INT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
set param3 = 0;
set param3 = (select count(*) from users where username=stuff and userpassword=pass);
select #param3;
END
And in C# side, I attempt to get this OUT parameter. Now, this is after multiple iterations, where I have gutted what the function used to be, and boiled it down to two issues: 1. The OUT parameters won't work, and 2. Even though Visual studio passes IN parameters, SQL refuses to recognize them.
protected void Login_Authenticate(object sender, AuthenticateEventArgs e)
{
using (MySqlConnection con = new MySqlConnection(strcon))
{
con.Open();
MySqlCommand com = new MySqlCommand("CALL login(#stuff, #pass, #param3);", con);
com.CommandType = CommandType.Text;
com.Parameters.Add("#stuff", MySqlDbType.VarChar);
com.Parameters["#stuff"].Value = Login.UserName;
com.Parameters.Add("#pass", MySqlDbType.VarChar);
com.Parameters["#pass"].Value = Login.Password;
try
{
obj = com.ExecuteScalar();
objparam = com.Parameters["param3"].Value;
if (Convert.ToInt32(obj) != 0)
{
Response.Redirect("Welcome.aspx");
}
else
{
Login.PasswordRequiredErrorMessage = "invalid user name and password";
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
con.Close();
}
}
I believe the code and the pictures say more than I ever will.
C# DB Layer (DB Layer has conn as a connection string):
// Note: this is an instance (myDB in terms of the GUI Object)
using System.Data;
using MySql.Data.MySqlClient;
...
...
public long MultBySeven(long theNum)
{ // Call a Mysql Stored Proc named "multBy7"
// which takes an IN parameter, Out parameter (the names are important. Match them)
// Multiply the IN by 7 and return the product thru the OUT parameter
long lParam = 0;
using (MySqlConnection lconn = new MySqlConnection(connString))
{
lconn.Open();
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = lconn;
cmd.CommandText = "multBy7"; // The name of the Stored Proc
cmd.CommandType = CommandType.StoredProcedure; // It is a Stored Proc
// Two parameters below. An IN and an OUT (myNum and theProduct, respectively)
cmd.Parameters.AddWithValue("#myNum", theNum); // lazy, not specifying ParameterDirection.Input;
cmd.Parameters.AddWithValue("#theProduct", MySqlDbType.Int32);
cmd.Parameters["#theProduct"].Direction = ParameterDirection.Output; // from System.Data
cmd.ExecuteNonQuery(); // let it rip
Object obj = cmd.Parameters["#theProduct"].Value;
lParam = (Int32)obj; // more useful datatype
}
}
return (lParam);
}
C# GUI Test Layer:
private void btnTestInOut_Click(object sender, EventArgs e)
{ // This GUI Layer call thru the use of a business object or data layer object (`myDB`)
long localHere = myDB.MultBySeven(11);
}
Stored Procedure (take a number, multiply by 7):
DROP PROCEDURE IF EXISTS multBy7;
DELIMITER $
CREATE PROCEDURE multBy7
( IN myNum INT,
OUT theProduct INT
)
BEGIN
SET theProduct=myNum*7;
END$
DELIMITER ;
Debug View (read: it works. 11x7=77):
MySQL Connector 6.9.9.0 / Visual Studio 2015:
See also 5.10.1 Using Stored Routines from Connector/Net, age unknown.
You should set up a reference to the parameter
var param3 = new MySqlParameter();
param3.Direction = ParameterDirection.Output;
param3.DbType = // whatever the dbtype for int is or whatever you need.
param3.ParameterName = "param3";
com.Parameters.Add(param3);
in your try block, insert
var result = com.ExecuteReader(); // or com.ExecuteScalar();
after you execute that, your parameter should have the value populated and you should be able to also read the SP results (select).
var paramResult = param3.Value;
Reading the results of the SP can be done as reader or scalar.
// execute reader
while (result.Read()) {
int value = result.GetInt32(0));
} /* read returned values in result */
// execute scalar
int value;
if (int.TryParse($"{result}", out value)) {
/* do something with value */
}
/************************************************/
This block should get you where you need to go
const string strcon = "whatevs";
using (MySqlConnection con = new MySqlConnection(strcon))
{
const string sql = "login";
MySqlCommand com = new MySqlCommand(sql, con);
com.CommandType = CommandType.StoredProcedure;
var stuffParam = new MySqlParameter("stuff", stuffValue);
var passParam = new MySqlParameter("pass", passValue);
var param3Param = new MySqlParameter();
param3Param.ParameterName = "param3";
param3Param.DbType = DbType.Int32;
param3Param.Direction = ParameterDirection.Output;
com.Parameters.Add(stuffParam);
com.Parameters.Add(passParam);
com.Parameters.Add(param3Param);
try
{
var scalarResult = com.ExecuteScalar();
// because you used select #param3 in your sp.
int value;
if (int.TryParse($"{scalarResult}", out value))
{
//do something with value
}
//// because you used select #param3 in your sp.
//var readerResult = com.ExecuteReader();
//if (readerResult.Read())
//{
// //
// value = readerResult.GetInt32(0);
//}
int param3Returned;
if(int.TryParse($"{param3Param.Value}", out param3Returned))
{
// do something with param3Returned
}
}
catch (Exception ex)
{
// do something with ex
}
}
How to properly do the following update:
using (OracleConnection conn = new OracleConnection())
using (selCmd)
{
string sql1 = "update Table1 set name = joe where id = 10;"
string sql2 = "update Table2 set country = usa where region = americas;"
string sql3 = "update Table3 set weather = sunny where state = CA;"
string sql4 = "update Table4 set engine = v8 where maker = benz;"
cmdUpdate.CommandText = sql(#);
cmdUpdate.Connection = conn;
recs = cmdUpdate.ExecuteNonQuery();
}
I am aware of all or nothing if it's a transaction but I just to see how it works with correct approach.
I'm thinking iterate an array of items [sql1,sql2,sql3,sql4] and pass sql(#) in the CommandText and perform ExecuteNonQuery each time.
If I remember correctly, it is possible to concatenate multiple SQL statements in one string separated by semi-colons (;). Otherwise, there is nothing wrong with executing multiple ExecuteNonQuery() calls.
string sql1 = "BEGIN update Table1 set name = 'joe' where id = 10;",
sql2 = "update Table2 set country = 'usa' where region = 'americas';",
sql3 = "update Table3 set weather = 'sunny' where state = 'CA';",
sql4 = "update Table4 set engine = 'v8' where maker = 'benz'; END;";
string sql = string.Format("{0}{1}{2}{3}",sql1,sql2,sql3,sql4);
using (OracleConnection conn = new OracleConnection())
using (OracleCommand cmdUpdate = new OracleCommand(sql, conn))
{
conn.Open();
recs = cmdUpdate.ExecuteNonQuery();
}
I recently came across this issue in some old code. We dynamically build chain of SQL calls (with support for Oracle and Sql Server). Since there is no current Oracle production implementation, nobody tested Oracle operation and customer bugs are not coming in. I found a code that builds chain of commands and then, for Oracle it uses String.Split(';'). Then, it uses a loop to execute each statement in transaction: rowsAffecter += ExecuteNonQuery....
I don't like this idea because without parameterization it is dangerous approach, since some data can contain ;. But even if parameterization is in place...
... one of the issues of making anonymous block for Oracle ("begin... end;") is that ExecuteNonQuery will not return number of rows (returns -1), which is sometimes needed to judge if something got updated or not.
to solve this issue I've done this
private string AppendOracleCountOrNothing(StringBuilder sql)
{
if (_myProvider == Providers.Oracle)
sql.AppendLine("rowCnt := rowCnt + SQL%ROWCOUNT;");
}
public void SomeMethod()
{
var longSqlChain = new StringBuilder(2000);
longSqlChain.Append("Insert into table...;");
AppendOracleCountOrNothing(longSqlChain);
if (someCondition)
{
longSqlChain.AppendLine("Update anotherTable...;");
AppendOracleCountOrNothing(longSqlChain);
}
// may be, add some more sql to longSqlChain here....
int rowsAffected;
if (_myProvider == Providers.Oracle)
{
longSqlChain.Insert(0, #"DECLARE
rowCnt number(10) := 0
BEGIN
").AppendLine(#":1 := rowCnt;
END;");
// Now, here we have some abstract wrappers that hide provider specific code.
// But the idea is to prepare provider specific output parameter and then parse its value
IDataParameter p = ParameterWrapper.PrepareParameter(":1", 0, ParameterDirection.Output, myProvider); // note IDataParameter
SqlExecWrapper.ExecuteNonQuery(_myProvider, CommandType.Text, sql, new[]{p});
rowsAffected = p.GetParameterValue(); // GetParameterValue is an extension on IDataParameter
}
else // sql server
{
rowsAffected = SqlExecWrapper.ExecuteNonQuery(_myProvider, CommandType.Text, sql, null);
}
}
This way we make one trip to DB and get the return number of rows affected by this call. and queries can be parameterized as well. Again, better to develop abstraction layer, so, you can call something like parameterizer.CreateParameter(10), which will add parameter to collection and generate :1, :2, :3, etc. (oracle) and #1, #2, #3, etc. (sql server), in your sql statement.
Another approach is to create a simple extension method (ExecuteMultipleNonQuery) that simply splits the string on all semicolons and executes each statement in a loop:
public static class DbCommandExtensions {
public static void ExecuteMultipleNonQuery(this IDbCommand dbCommand)
{
var sqlStatementArray = dbCommand.CommandText.Split(new string[] {";"}, StringSplitOptions.RemoveEmptyEntries);
foreach (string sqlStatement in sqlStatementArray)
{
dbCommand.CommandText = sqlStatement;
dbCommand.ExecuteNonQuery();
}
}
}
I need to retrieve a value from a field in database. I have the used following code. but the value checkOrderId (which I need) shows the SQL string instead of the value from database. I don't know why it is doing so. Could somebody help me please?
string connectionString = "Data Source = xxyyzz;Initial Catalog = xyz; Integrated Security = True";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string tableName = "[GIS].[SecondaryTraffic].[PotentialBackHauls]";
string checkOrderId = "Select TOP 1 OrderID From" + tableName + "ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
//cmd.ExecuteNonQuery();
OpenPop.Pop3.Pop3Client popConn = new OpenPop.Pop3.Pop3Client();
if (orderIdentity == checkOrderId)
{
popConn.DeleteMessage(messageNumber);
}
connection.Close();
I am new and dont have reputation to answer my question immediately. With everybody's help, i got this one solved...Great help, thanx everybody...following is my code.
string connectionString = "Data Source = EAEDEV;Initial Catalog = GIS; Integrated Security = True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string tableName = "[GIS].[SecondaryTraffic].[PotentialBackHauls]";
string checkOrderId = "Select TOP 1 OrderID From " + tableName + " ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
string valueReturned = (string)cmd.ExecuteScalar();
OpenPop.Pop3.Pop3Client popConn = new OpenPop.Pop3.Pop3Client();
if (orderIdentity == valueReturned)
{
popConn.DeleteMessage(messageNumber);
}
connection.Close();
}
You need to execute the query and check the results, here you are just comparing a string with the query SQL.
Please see here
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson03
for a tutorial.
Your expectation of the result being set into checkOrderId is incorrect. In this instance checkOrderId is just the query to execute and not the actual result.
You need to read the value back from executing the command:
using (var connection = new SqlConnection(connectionString))
using (var comm = new SqlCommand("Select TOP 1 OrderID From [GIS].[SecondaryTraffic].[PotentialBackHauls] ORDER BY InsertDate DESC", connection))
{
connection.Open();
object result = comm.ExecuteScalar(); // This is the key bit you were missing.
if (result != null)
{
// You can cast result to something useful
int orderId = (int)result;
}
} // Both comm and connection will have Dispose called on them here, no need to Close manually.
ExecuteScalar returns the value in the first cell (ie, column 1 row 1) as an object that you can cast to a better type (depending on what type it was in the result-set schema).
If you need to read multiple values, you need to look at ExecuteReader.
There are also other ways of doing this using output parameters, but that would pollute the point of the answer.
You can add space to your query
"Select TOP 1 OrderID From " + tableName + " ORDER BY InsertDate DESC";
Nota : I suggest you to use AddWithValue method with your parameter
string checkOrderId = "Select TOP 1 OrderID From #tableName ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
cmd.Parameters.AddWithValue("#tableName", tableName );
Link : http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlparametercollection.addwithvalue.aspx
You don't actually run your command anywhere. Instead of the commented-out cmd.ExecuteNonQuery, you should look into the ExecuteScalar method, which allows you to read back a single result value from a query - which is what your query returns.
Add
int i = (Int32) cmd.ExecuteScalar();
right after
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
then the variable i will contain the order id
No, this is not correct. You are comparing the variable orderId to your query string. I doubt that's what you want to do. I imagine you'd be better off calling cmd.ExecuteScalar() to retrieve the actual OrderID value. As noted by other answers, your query string is missing a space. But most importantly, it is bad practice to construct SQL queries in code. Although I can't see a security issue with this code, if you continue to use this method you will probably write code that is vulnerable to SQL injection. I recommend you learn to either use parameters or LINQ to build your queries.