How I will save this to stored procedure? And run the stored procedure in c#?
string a = "Select * from EmpTable Where EmpName Like #SearchItem";
using (SqlCommand SqlCommand = new SqlCommand(" "+ a +" ", myDatabaseConnection))
{
SqlCommand.Parameters.AddWithValue("#SearchItem", "%" + textBox1.Text + "%");
}
Stored procedure:
CREATE PROCEDURE SearchSP
#SearchItem nvarchar(MAX)
AS
BEGIN
Select *
from EmpTable
Where EmpName Like '%' + #SearchItem + '%'
END
GO
Code:
using (SqlCommand cmd= new SqlCommand("SearchSP", myDatabaseConnection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#SearchItem", textBox1.Text);
//rest of the code
}
What your Saying is you want the string gone and to call a stored procedure instead that has this SQL code inside? If that's the case..
Presuming SQL server 2008 management studio..
In management studio expand your "database", Then Expand "Programmability"...
Right click create new stored procedure and delete all code inside.
then type in the following.
USE [YourDataBaseName]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AnyName]
#SearchItem as nvarchar(MAX)
AS
Select * from EmpTable Where EmpName Like #SearchItem
click run/execute and refresh your database, if you look in the stored proc folder you should see your new stored procedure.
Then in your (presuming C#.Net) code.
public string GetUserFinal(string _userInput)
{
string temp = "";
using (SqlConnection myConn = new SqlConnection(Conn))
{
using (SqlCommand myCommand = new SqlCommand())
{
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "dbo.your procedure name";
myCommand.Parameters.AddWithValue("#SearchItem", _userInput);
SqlDataReader reader = myCommand.ExecuteReader();
myCommand.Connection = myConn;
While (reader.read())
{
//populate a string? or do something else?
}
}
}
return temp;
}
A better way would be to Strongly type all of this. So i would create a Model of whatever you now the fields and types will be, then create a list And iterate through that list to bind from this Function. But as you can see the basics, this should work just check the syntax.
Create a stored procedure something like below:
Create Procedure dbo.Test
#SearchItem
AS
BEGIN
BEGIN TRY
IF EXISTS(SELECT 1 FROM dbo.Table WHERE EmpName LIKE '%'+#SearchItem+'%')
SELECT * FROM dbo.Table WHERE EmpName LIKE '%'+#SearchItem+'%'
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS 'ErrorNumber', ERROR_MESSAGE() AS 'ErrorMessage', ERROR_SEVERITY() AS 'ErrorSeverity', ERROR_STATE() AS 'ErrorState', ERROR_LINE() AS 'ErrorLine'
RETURN ERROR_NUMBER()
END CATCH
END
Now you can refer this sp in code-behind as below:
SqlConnection xconn=new SqlConnection(Write your connection string);
SqlCommand xcommand=new SqlCommand("Test",xconn);
xcommand.CommandType=CommandType.StoredProcedure;
xcommand.Parameters.AddWithValue("#SearchItem",DbType.String,txtBox1.Text);
xconn.Open();
xCommand.ExecuteNonQuery();
xconn.Close();
this will be your stored proc, (haven't tested the code):
CREATE PROCEDURE TestStoredProc
#SearchItem nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
Select *
from EmpTable
Where EmpName Like '%' + #SearchItem + '%'
END
GO
Then in code side do this:
using (var conn = new SqlConnection(connectionString))
using (var command = new SqlCommand("TestStoredProc", conn) {
CommandType = CommandType.StoredProcedure, Parameters.AddWithValue("#SearchItem",textbox.Text)}) {
}
Related
I have looked into this issue before I posted, and found some solutions which I have tried to apply, but no luck in it working.
I have a stored procedure to insert records into a database. I want to return a value as a status (I have seen that you can only return an int on a RETURN and that is fine in this case).
ALTER PROCEDURE [dbo].[_example]
-- Add the parameters for the stored procedure here
#Parameters)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Example int
DECLARE #retVal int = 0
IF (#example is null)
BEGIN
SET #retVal +=1;
END
return #retVal
END
in my c# code I have written this:
public static int ExecuteSPWithReturnValue(string queryString)//not returning the value correctly
{
connection.Open();
SqlCommand command = new SqlCommand(queryString, connection)
{
CommandTimeout = 0
};
SqlParameter retVal = command.Parameters.Add("#retVal", SqlDbType.Int);
retVal.Direction = ParameterDirection.ReturnValue;
command.ExecuteNonQuery();
int result = (int)retVal.Value;
connection.Close();
return result;
}
I call it from another class like this:
int returnStatus;
returnStatus = SQLUtility.ExecuteSPWithReturnValue("EXEC dbo._example " +
"#param1= '" + string + "'," +
"#param2= '" + string + "'," +
"#param3 = '" + string + "'," +
"#param4 ='" + string + "'");
but it just returns 0 no matter what. I know the value of the parameter is between 0-3, but that's not being passed into the int return Status.
Why?
The issue seems to be that you are sending through an ad-hoc batch, which is not returning the value.
You could change your batch to
DECLARE #retval int;
EXEC #retval = dbo._example .....
RETURN #retval;
But it's much better to just execute the procedure directly, using CommandType.StoredProcedure. This avoids nasty SQL injection also.
Note also that you should dispose the connection and command objects with using, do not cache them
public static int ExecuteSPWithReturnValue(string queryString, bool isProcedure, params SqlParameter[] parameters)
{
using (var connection = new SqlConnection(myConnectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
{
if(isProcedure)
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 0;
command.Parameters.AddRange(parameters);
var retVal = command.Parameters.Add("#retVal", SqlDbType.Int);
retVal.Direction = ParameterDirection.ReturnValue;
connection.Open();
command.ExecuteNonQuery();
return (int)retVal.Value;
}
I have an asp app that should be able to let a user update an entry in a sql server database. When I run my stored procedure though in my method, nothing happens to the database.
public void updateFeature(Feature updatedFeature)
{
using (SqlConnection sqlConnection = new SqlConnection(GetConnectionString(updatedFeature.Environment)))
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.CommandText = "usp_UpdateFeature";
sqlCommand.Parameters.AddWithValue("#FeatureName", updatedFeature.FeatureName);
sqlCommand.Parameters.AddWithValue("#FeatureID", updatedFeature.FeatureID);
sqlCommand.Parameters.AddWithValue("#FeatureDescription", updatedFeature.Description);
sqlCommand.Parameters.AddWithValue("#FieldName", updatedFeature.FieldName);
sqlCommand.Parameters.AddWithValue("#OnOffSwitch", updatedFeature.IsOn);
sqlCommand.Parameters.AddWithValue("#ChannelID", updatedFeature.ChannelID);
sqlCommand.Parameters.AddWithValue("#ProductID", updatedFeature.ProductID);
sqlConnection.Open();
int numberOfRowsChanged = sqlCommand.ExecuteNonQuery();
}
}
and my stored procedure looks like this
ALTER PROCEDURE [dbo].[usp_UpdateFeature]
(
#FeatureID int,
#FeatureName varchar(30),
#FeatureDescription varchar(200) = null,
#FieldName varchar(40),
#OnOffSwitch bit,
#ChannelID varchar(3),
#ProductID varchar(2)
)
AS
SET NOCOUNT ON
UPDATE FM_Feature
SET FeatureName = #FeatureName,
FeatureDescription = #FeatureDescription,
FieldName = #FieldName,
OnOffSwitch = #OnOffSwitch,
ProductID = #ProductID,
ChannelID = #ChannelID
WHERE FeatureID = #FeatureID
The numberOfRowsChanged parameter returns -1 but I do not get any exceptions or errors. Is there something that I am missing or not understanding?
I think that you need to open your connection before you create your command, i hope that will be helpful for you .
using (SqlConnection sqlConnection = new SqlConnection(GetConnectionString(updatedFeature.Environment))
sqlConnection.Open();
using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.CommandText = "usp_UpdateFeature";
sqlCommand.Parameters.AddWithValue("#FeatureName", updatedFeature.FeatureName);
sqlCommand.Parameters.AddWithValue("#FeatureID", updatedFeature.FeatureID);
sqlCommand.Parameters.AddWithValue("#FeatureDescription", updatedFeature.Description);
sqlCommand.Parameters.AddWithValue("#FieldName", updatedFeature.FieldName);
sqlCommand.Parameters.AddWithValue("#OnOffSwitch", updatedFeature.IsOn);
sqlCommand.Parameters.AddWithValue("#ChannelID", updatedFeature.ChannelID);
sqlCommand.Parameters.AddWithValue("#ProductID", updatedFeature.ProductID);
int numberOfRowsChanged = sqlCommand.ExecuteNonQuery();
}
enjoy it .
I created a FILETABLE on SQL Server 2014 with all the default options with a view for retrieving data and stored procedures for inserting and deleting files. Please note that non-transactional access is not enabled on the database because the files shouldn't be visible on the file system.
The problem is that when I retrieve a file from the table and write it to disk, it isn't identical to the original and can't be opened with the associated program.
Code for the view:
SELECT stream_id, file_stream, name, CAST(creation_time AS DateTime) AS DateCreated, CAST(last_write_time AS DateTime) AS DateUpdated FROM dbo.DocumentFiles
Code for the insert procedure:
create PROCEDURE [dbo].[sp_DocumentFiles_create]
-- Add the parameters for the stored procedure here
#name nvarchar(255),
#data varbinary(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #id uniqueidentifier;
set #id = NEWID();
insert into DocumentFiles (stream_id, file_stream, name) VALUES(#id, #data, #name);
select #id;
END
Code used for reading:
DocumentFile result = null;
SqlCommand comm = new SqlCommand("SELECT * from DocumentView where stream_id = #id", conn);
comm.Parameters.Add(new SqlParameter("#id", id));
try
{
conn.Open();
SqlDataReader reader = comm.ExecuteReader();
while (reader.Read())
{
result = new DocumentFile();
result.stream_id = (Guid)reader["stream_id"];
result.file_stream = (byte[])reader["file_stream"];
result.name = reader["name"].ToString();
result.DateCreated = Convert.ToDateTime(reader["DateCreated"]);
result.DateUpdated = Convert.ToDateTime(reader["DateUpdated"]);
}
}
catch
{
}
finally
{
conn.Close();
}
return result;
Code used for inserting:
public Guid? Insert(DocumentFile obj)
{
Guid? result = null;
SqlCommand comm = new SqlCommand("sp_DocumentFiles_create", conn);
comm.CommandType = System.Data.CommandType.StoredProcedure;
comm.Parameters.Add(new SqlParameter("#name", obj.name));
comm.Parameters.Add(new SqlParameter("#data", obj.file_stream));
try
{
conn.Open();
result = comm.ExecuteScalar() as Guid?;
}
finally
{
conn.Close();
}
return result;
}
The only files that I managed to insert and retrieve intact are image files. I tried using various ms office documents (.doc, .docx, .pptx, etc) as well as archives (rar, zip).
i have that code using LINQ to call a stored procedure to save some data into database then return two variables from the stored procedure.
[ASP.NET code]
dbDataContext dbo = new dbDataContext();
dbo.AddNewDoctor(doctorName, email, password, ref DocId, ref result);
[SQL]
create PROCEDURE [dbo].[AddNewDoctor]
#doctorname nvarchar(100),
#email nvarchar(100),
#password nvarchar(MAX),
#docId int out,
#Result int out
AS
BEGIN
SET NOCOUNT ON;
declare #idCounter int
select #idCounter = count(*) from dbo.doctors
if EXISTS (select * from dbo.doctors where e_mail = #email)
begin
SET #Result = -1
set #docId= 0
end
else
begin
INSERT INTO [dbo].[doctors]
([doctor_id]
,[doctorname]
,[e_mail]
,[password]
VALUES
((#idCounter +1)
,#docotorname
,#email
,#password
)
SET #Result = 1
set #docId= (#idCounter + 1)
end
END
this code work very well what i want to do now to use ADO instead of LINQ, the problem with me is that i can't pass the ref variable as in LINQ so how can i do it using ADO
You'll have to do something like this. Use ParameterDirection
SqlParameter output = new SqlParameter(paramName, dbType);
output.Direction = ParameterDirection.Output;
command.Parameters.Add(output);
In your case you've to use SqlDbType.Int. Use Value property to read return value.
SqlParameter output = new SqlParameter(paramName, SqlDbType.Int);
output.Direction = ParameterDirection.Output;
command.Parameters.Add(output);
int Result = (int) output.Value; or int? Result = (int?) output.Value;
Try this
using (SqlConnection con = new SqlConnection("Your connection string"))
{
con.Open();
SqlCommand mycommand = new SqlCommand();
mycommand.Connection = con;
mycommand.CommandText = "dbo.AddNewDoctor";
mycommand.CommandType = CommandType.StoredProcedure;
mycommand.Parameters.AddWithValue(doctorName);
mycommand.Parameters.AddWithValue(email);
mycommand.Parameters.AddWithValue(password);
mycommand.Parameters.AddWithValue(ref DocId);
mycommand.Parameters.AddWithValue(ref result);
mycommand.ExecuteNonQuery();
}
Hope this helps thanks.
Refer to this article, there is an working example:
http://csharp-guide.blogspot.de/2012/05/linq-to-sql-call-stored-procedure-with_25.html
I have a stored procedure that adds a user and at each permission I add, I want to start building a success message.
My stored procedure runs fine but how do I get that success message back into a message dialog in my app?
I want to display the below #text in a messagebox in my C# app.
DECLARE #text NVARCHAR(1000)
SET #text = 'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.'
SELECT #text
This is my call in my C# app:
public DataTable CreateOrDropUser(string dataBase, string procedure, SqlParameter[] parameters)
{
try
{
if (dataBase.Length > 0) { procedure = dataBase + ".." + procedure; } //Set procedure to DBNAME..ProcedureName
SqlCommand cmd1 = new SqlCommand(procedure, con);
cmd1.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter p in parameters)
{
if (p != null)
{
cmd1.Parameters.Add(p);
}
}
con.Open();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd1);
da.Fill(dt);
con.Close();
MessageBox.Show("Success"); //This should display the #text variable in my proc
return dt;
}
catch (Exception ex)
{
try
{
if (con.State == ConnectionState.Open)
{
con.Close();
}
}
catch
{
MessageBox.Show("Could not connect to database. Check settings. " + ex.Message, "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
MessageBox.Show(ex.Message);
return null;
}
}
My Stored proc, Just focus on sections by all the prints, that's the text i'm adding:
ALTER PROCEDURE [dbo].[AdminDevUserCreate]
#SQLLoginName varchar(50),
#SQLLoginPass varchar(50)
AS
DECLARE #text NVARCHAR(1000)OUTPUT
--PRINT 'Create SQL Login'
SET #text = 'Create SQL Login ' + #SQLLoginName
-- USE [Master]
EXEC(' USE [master] CREATE LOGIN [' + #SQLLoginName + '] WITH PASSWORD=''' + #SQLLoginPass + ''', DEFAULT_DATABASE=[TestAudit], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF')
--PRINT 'Add Server Roles'
SET #text += + CHAR(13)+CHAR(10) + 'Add Server Roles'
--Add Server roles
EXEC master..sp_addsrvrolemember #loginame = #SQLLoginName, #rolename = N'bulkadmin'
EXEC master..sp_addsrvrolemember #loginame = #SQLLoginName, #rolename = N'processadmin'
EXEC master..sp_addsrvrolemember #loginame = #SQLLoginName, #rolename = N'securityadmin'
--PRINT 'Allow SQL Agent Job Manage'
SET #text += + CHAR(13)+CHAR(10) + 'Allow SQL Agent Job Manage'
--USE [MSDB]
EXEC ('msdb..sp_addrolemember ''SQLAgentOperatorRole'', ''' + #SQLLoginName + '''')
--PRINT 'Allow Trace'
SET #text += + CHAR(13)+CHAR(10) + 'Allow Trace'
--Allow trace (SQL Profiler)
--USE [MASTER]
EXEC (' USE [MASTER] GRANT ALTER TRACE TO ' + #SQLLoginName )
--PRINT 'Prevent admin proc changes '
SET #text += + CHAR(13)+CHAR(10) + 'Prevent admin proc changes '
EXEC ('USE [TestAudit] DENY ALTER ON [TestAudit].[dbo].[Admin] TO ' + #SQLLoginName) --Prevents changes to Admin function
--PRINT 'Prevent database trigger changes'
SET #text += + CHAR(13)+CHAR(10) + 'Prevent database trigger changes'
EXEC ('USE [TestAudit] DENY ALTER ANY DATABASE DDL TRIGGER TO ' + #SQLLoginName) --Prevents modify of [SchemaAuditTrigger]
PRINT #text
Select #text
Your best bet is to use a output parameter.
In your stored procedure add the parameter #text nvarchar(1000) OUTPUT then in your code add an extra parameter with the name #text and set the parameter direction to output.
then just add the line SET #text = 'This is line 1.' + CHAR(13)+CHAR(10) + 'This is line 2.' in your stored procedure
Edit: My answer is if you don't want this to affect your current query, if i misinterpreted your question please let me know. Also to get the value, after you execute the query you can get the value from the #name parameter using .Value
Edit 2: Example Code Should look something like
//Add these lines
SqlParameter text = new SqlParameter("#name", SqlDbType.NVarChar);
text.Direction = ParameterDirection.Output;
cmd1.Parameters.Add(text);
con.Open();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd1);
da.Fill(dt);
con.Close();
//Change this line
MessageBox.Show(text.Value); //This should display the #text variable in my proc
if you need help with the stored procedure please post it and i'll give a example with that too
Edit 3: Quick example Tested with a quick example. The C# code:
using (SqlConnection connection = new SqlConnection(#"Data Source=.\SQLExpress;Initial Catalog=TestDB;Integrated Security=True"))
{
connection.Open();
using (SqlCommand command = connection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "Test";
SqlParameter text = new SqlParameter("#Text", SqlDbType.NVarChar, 1000);
text.Direction = ParameterDirection.Output;
command.Parameters.Add(text);
using (DataTable dt = new DataTable())
{
using (SqlDataAdapter da = new SqlDataAdapter(command))
{
da.Fill(dt);
}
}
Trace.WriteLine(text.Value);
connection.Close();
}
}
The Stored Procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE Test
#Text Nvarchar(1000) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #Text = 'test'
END
GO
Worked fine for me if you want to check it against yours for differences
Edit 4: In your stored procedure the #text needs to be a parameter so instead of
ALTER PROCEDURE [dbo].[AdminDevUserCreate]
#SQLLoginName varchar(50),
#SQLLoginPass varchar(50)
AS
DECLARE #text NVARCHAR(1000)OUTPUT
make it
ALTER PROCEDURE [dbo].[AdminDevUserCreate]
#SQLLoginName varchar(50),
#SQLLoginPass varchar(50),
#text NVARCHAR(1000) OUTPUT
AS
also when creating the SqlParameter use
SqlParameter text = new SqlParameter("#Text", SqlDbType.NVarChar, 1000);
which should get rid of the size issue as you are telling it that the parameter is NVARCHAR(1000)
the line
PRINT #text
Select #text
shouldn't be needed
Informational messages can be retrieved from SqlConnection.InfoMessage event. They can be raised in T-SQL code using RAISERROR with severity 0-9.
public DataTable CreateOrDropUser(string dataBase, string procedure, SqlParameter[] parameters)
{
SqlconnecitonStringBuilder scsb = new SqlConnectionStringBuilder (connstring);
scsb.Database = database;
using (SqlConnection con = new SqlConnection (scsb.ConnectionString))
{
StringBuilder sb = new StringBuilder ();
con.Open ();
SqlCommand cmd1 = new SqlCommand(procedure, con);
cmd1.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter p in parameters)
{
if (p != null)
{
cmd1.Parameters.Add(p);
}
}
conn.InfoMessage += (args =>
{
sb.AppendLine (args.Message);
});
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd1);
da.Fill(dt);
MessageBox.Show(sb);
return dt;
}
}
And in T-SQL:
RAISERROR(N'This is line %d', 0,0,1);
RAISERROR(N'This is line %d', 0,0,2);
If you are using MVC then there is an excellent sample here. I have used it in multiple projects and found it fantastic.
Also you should really be wrapping your SqlCommand and SqlConnection object in using statements to stop leaky connections.
Note: this can be adapted to WebForms without too much trouble.
MessageBox.Show(dt.Rows[0][0].Tostring());
or
Use a output parameter