c# ADO set context_info for SQL INSERT TRIGGER - c#

I have to use an existing INSERT trigger which uses CONTEXT_INFO...
How can I pass "context_info" to a c# SqlCommand so that this trigger keeps working correctly?
Usage in SQL-Trigger:
select #ctxt=context_info from master.dbo.sysprocesses where spid = ##spid
set #session=substring(#ctxt,1,4)
set #contextid=substring(#ctxt,5,4)
set #ntduser=substring(#ctxt,9,120)
Tried:
//string strContext = "declare #context_info varbinary(30) set #context_info = cast('abcdefghijklmnopqrstuv1234567890' as varbinary(30)) set context_info #context_info";
///////////////
SqlCommandBuilder cb = new SqlCommandBuilder(da);
da.UpdateCommand = cb.GetUpdateCommand();
//da.UpdateCommand.CommandText= da.UpdateCommand.CommandText.Replace(" WHERE ", strContext+" WHERE ");
//da.UpdateCommand.CommandText = "SET CONTEXT_INFO 0x1 " + da.UpdateCommand.CommandText;
da.Update(dataTable);
da.Dispose();
see commented out code...
In my SQL Trigger "context_info" was always empty
Already read that:
https://social.msdn.microsoft.com/Forums/en-US/4a0ecb28-11cb-45ec-adbd-d72ac65b158a/how-to-pass-net-applications-parameter-to-a-trigger?forum=transactsql
but also does not work.
Isn't there a sample out there where context_info is passed to SqlCommand or SqlConnection or SqlTransaction?

I used something like this (simplified) once to set some information (guid) so that it can be retrieved from inside a trigger ...
string sql = $"DECLARE #session uniqueidentifier; SET #session = '{guid}'; SET CONTEXT_INFO #session";
var cmd = new SqlCommand(sql, connection, transaction);
cmd.ExecuteNonQuery();
Be sure not to close the connection between setting the context_info and invokation of the trigger ...

Related

How to combine multiple SQL Commands into one?

Is it possible to optimize the following queries by merging them inside a single SQLCommand?
SqlCommand cmd = new SqlCommand
{
CommandType = CommandType.Text,
CommandText = "DELETE FROM cbu_naslovi WHERE [ID]='" + CurrentID + "'",
Connection = con
};
SqlCommand cmd1 = new SqlCommand
{
CommandType = CommandType.Text,
CommandText = "DELETE FROM cbu_deli WHERE [IDX]='" + CurrentID + "'",
Connection = con
};
cmd.ExecuteNonQuery();
cmd1.ExecuteNonQuery();
EDIT: Working solution, as suggested by the community answers bellow
SqlCommand cmd = new SqlCommand
{
CommandType = CommandType.Text,
CommandText = "DELETE FROM cbu_naslovi WHERE [ID] = #CurrentID; DELETE FROM cbu_deli WHERE [IDX] = #CurrentID",
Connection = con
};
cmd.Parameters.AddWithValue("#CurrentID", CurrentID);
cmd.ExecuteNonQuery();
Yes, you can just separate them with a semicolon. For example I have code that executes the following in a single call
SET NOCOUNT ON;
DECLARE #decimalDate DECIMAL(12,0);
DECLARE #charDate CHAR(12);
DECLARE #utcDate DATETIMEOFFSET;
DECLARE date_cursor CURSOR FOR SELECT {1} FROM {0} WHERE ISNULL({1},0)!=0;
OPEN date_cursor;
FETCH NEXT FROM date_cursor INTO #decimalDate;
WHILE ##FETCH_STATUS=0
BEGIN
BEGIN TRY SET #charDate=CONVERT(CHAR(12),#decimalDate);
SET #utcDate=SwitchOffset(
CONVERT(DATETIME,'20'
+SUBSTRING(#charDate,1,2)+'-'+SUBSTRING(#charDate,3,2)+'-'
+SUBSTRING(#charDate,5,2)+' '+SUBSTRING(#charDate,7,2)+':'
+SUBSTRING(#charDate,9,2)+':'+SUBSTRING(#charDate,11,2)
,121) AT TIME ZONE '{3}',0);
END
TRY BEGIN CATCH
SET #utcDate=SysUtcDateTime();
END CATCH;
BEGIN
TRY UPDATE {0} SET {2}=#utcDate WHERE CURRENT OF date_cursor;
END TRY
BEGIN CATCH END CATCH;
FETCH NEXT FROM date_cursor INTO #decimalDate;
END;
CLOSE date_cursor;
DEALLOCATE date_cursor;
There are exceptions. For instance the "create procedure" statement must be the first statement of a block. But most DML can be batched like this.
You can write it like this:
SqlCommand cmd = new SqlCommand
{
CommandType = CommandType.Text,
CommandText = $"DELETE FROM cbu_naslovi WHERE [ID]='{CurrentID}';DELETE FROM cbu_deli WHERE [IDX]='{CurrentID}'",
Connection = con
};
if you need to run Non Query operation, you could try to execute bunch of commands by using Server object.
benefit: you could use GO in SQL statement. Command does not allow to use GO.
server.ConnectionContext.ExecuteNonQuery("your SQL statement -- could be 100 statements with hundrends of GO commands", ExecutionTypes.Default)
server variable has type Server

C# MS SQL Update statement not updating database

I have a local MS SQL Database, and I want to update one of it's bit field.
I have the following code:
static void UpgradeVevo(string nev)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("UPDATE Vevok SET Torzsvendeg=True Where Nev=" + nev, connection);
command.ExecuteNonQuery();
}
Console.WriteLine(nev+" mostmár törzsvendég");
}
Torzsvendeg is a bit datatype(I have tried to set its value to 1 too), and Nev is varchar.
The connectionstring should be fine, since I have tried Select in another method and it works fine. The above code throws no exceptions, but the table does not get updated.
I have tried to find an answer for quite some time, with no success :/. Thank you for your help in advance!
True should be in a single quote since it's a string literal like
UPDATE Vevok SET Torzsvendeg='True'
Well brother, you are messed up with quotes. Your query should look like
"UPDATE Vevok SET Torzsvendeg = 1 Where Nev = '" + nev + "'"
Again, use parametarized query and not this concatenated one to avoid SQL Injection
If the column is a boolean (bit in sql server) then you will have to write
Torzsvendeg=1
instead of
Torzsvendeg='True'
or
Torzsvendeg=True
Edit:
Please try this:
static void UpgradeVevo(string nev)
{
var connection = new SqlConnection(connectionString))
connection.Open(); // try doing this without a using
SqlCommand command = new SqlCommand("UPDATE Vevok SET Torzsvendeg=#enabled Where Nev=#nev", connection);
command.Parameters.AddWithValue(#"enabled", 1);
command.Parameters.AddWithValue(#"nev", "vevo123");
command.ExecuteNonQuery();
command.Parameters.Clear(); // always clear after executed
// close connection when you shut down your application
connection.Close();
connection.Dispose();
Console.WriteLine(nev+" mostmár törzsvendég");
}

Stored Procedure doesn't return records when called from C#, but works in SSMS

I have a stored procedure that correctly returns records when I call it from a SSMS query.
Here is the stored procedure:
CREATE PROCEDURE [dbo].[q_CheckRecords]
#ItemIDS AS VARCHAR(40)
AS
BEGIN
SET NOCOUNT ON
SELECT *
FROM q_Warehouse80_OOS_ItemsNeedingNotification
WHERE item_id = #ItemIDS
END
Calling this from a SSMS query like this:
exec [q_CheckOOSWarehouse80ItemsNeedingNotification] 'B30-R10000-B001'
It correctly returns a row, however when I use this C# code to call the stored procedure, I never get any rows returned.
SqlCommand cmd = null;
SqlDataReader myReader = null;
System.Data.SqlClient.SqlConnection conn = null;
conn = new System.Data.SqlClient.SqlConnection("Data Source=" + sSessionServer + ";database=" + sSessionDatabase + "; Integrated Security=SSPI");
String SQL = "[q_CheckOOSWarehouse80ItemsNeedingNotification]";
cmd = new SqlCommand();
cmd.CommandText = SQL;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Connection = conn;
cmd.Parameters.Add("#ItemIDS", SqlDbType.VarChar).Value = ItemsToBeChecked;
conn.Open();
myReader = cmd.ExecuteReader();
// check to see if any rows were returned.
if (myReader.HasRows)
{
while (myReader.Read())
{
// code to read fields in returned rows here
}
}
conn.Close();
It appears to be a problem with how C# defines the datatype being passed to the stored procedure, but I haven't found any information online on how to solve this problem.
If I were to changed the stored procedure so it's "hard coded"
#ItemIDS AS VARCHAR(40)
AS
BEGIN
SET NOCOUNT ON
select * from q_Warehouse80_OOS_ItemsNeedingNotification where item_id = 'B30-R10000-B001'
END
then the C# call to it correctly indicates that a row was "found".
Any help would be greatly appreciated.
When you don't specify the length of a varChar sql treats it as length 1.
cmd.Parameters.Add("#ItemIDS", SqlDbType.VarChar).Value = ItemsToBeChecked;
Your variable ItemsToBeChecked will be truncated, and I suspect there is nothing matching in your database with just the first character of that value.
Specify the length of the varchar
cmd.Parameters.Add("#ItemIDS", SqlDbType.VarChar, 40).Value = ItemsToBeChecked;
You can verify this is the case by putting a profiler on sql, and executing your c#. You will see the value passed to the #ItemIDS parameter is only 1 character long.
The issue you are facing is because you are not calling your stored procedure in your C# Code.

Unable to open connection using a "using var parameterized queries"

I have this scenario:
I have a table called "Entradas" and one called "Saidas". Both have
the column "data" and "hora". With that in mind, since the "data" and
"hora column of "entradas" mean that a car joined at that date and
time, and the values from the columns "data" and "hora" of "saidas"
are mean to be inserted as i click a button, inserting the current
date and time. I'm requesting a sql syntax that could insert the
values "data" and "hora" into the table "saidas" and update a value of
"entradas" called "sai" which is equal to 0 and i want it to change to
1 on button press.
And i have this procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `entradas_sai`(
IN ID_VEICULO VARCHAR(45), OUT retcode INT)
BEGIN
DECLARE _rollback BOOL DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET _rollback = 1;
START TRANSACTION;
INSERT INTO SAIDAS(data, hora) VALUES(date(now()) ,time(now()));
UPDATE ENTRADAS SET SAI=1;
IF '_rollback' THEN
SET retcode = 0;
ROLLBACK;
ELSE
SET retcode = 1;
COMMIT;
END IF;
END
And this is my actual code to run it on button click:
private void cmdSaida_Click(object sender, EventArgs e)
{
using (var cn = new MySqlConnection("server=localhost;user id=root;password=12345;persistsecurityinfo=True;database=portaria;allowuservariables=True"))
{
cn.Open();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "entradas_sai";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ID_veiculo", Grid1.SelectedCells[1].Selected);
cmd.Parameters["#id_veiculo"].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("#retcode", MySqlDbType.Int32);
cmd.Parameters["#retcode"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
var res = cmd.Parameters["#retcode"].Value;
cn.Close();
}
}
And my problem at the moment is that when i click the button, it doesn't execute my procedure neither my commands to open or close the connection. Any sugestions?
EDIT: After some research i found that my actual procedure sets all the values from 0 to 1 in column "sai" how can i do it so it only change the selected grid row value, based on "ID_Entrada"
You have a MySqlCommand object, but it's not associated with any connection. There has to be an active connection in order to execute a command.
You can associate it on the constructor:
MySqlCommand cmd = new MySqlCommand("entradas_sai", cn);
or after the constructor:
cmd.Connection = cn;

How to update MySql table row through C# console application?

I am writing a console application and fetch data from MySql table .
Code :
string connection = "Server=localhoht;Database=data;Uid=root;Pwd=root123";
MySqlConnection dbcon = new MySqlConnection(connection);
MySqlCommand selectData;
dbcon.Open();
selectData = dbcon.CreateCommand();
selectData.CommandText = "SELECT user_id, user_name,user_type FROM win_user WHERE user_type=1 ORDER BY user_id ASC ";
MySqlDataReader juh = selectData.ExecuteReader();
And its working fine. Now I want to update a row with the code below :
string updatedata = "UPDATE win_user SET user_type='1' WHERE user_id= '1'";
MySqlDataAdapter MyData = new MySqlDataAdapter();
MyData.UpdateCommand = new MySqlCommand(updatedata, dbcon);
But its not working.
You can run the commend "UPDATE win_user SET user_type='1' WHERE user_id= '1'" in any sql client tools, eg, navicat, to verify wheather it's correct on your mysql database.
The MySqlDataAdapter could be used to update rows in a database table using the Update method.
The Update method (link is for SqlServer but the concept is the same) has many overload, but basically it requires a DataTable with rows modified in some way ([RowState != DataRowState.Unchanged][2]) so the MySqlDataAdapter can pick the rows changed and apply the DeleteCommand, UpdateCommand and InsertCommand defined in the adapter
Your code above doesn't shown any kind of interaction with a datatable and you have a call to the Update method so there is no way for the update to occur.
You could, of course execute directly your command without any adapter involved
EDITed to change every user_type not 1 to 1
string updatedata = "UPDATE win_user SET user_type=1 WHERE user_type <> 1";
MySqlCommand cmd = new MySqlCommand(updatedata, dbcon);
int numOfRowsChanged = cmd.ExecuteNonQuery();

Categories