I want to show these SQL messages in c#
My C# code:
SqlCommand cmd = new SqlCommand();
cmd = con.CreateCommand();
string ab = "";
con.FireInfoMessageEventOnUserErrors = true;
con.InfoMessage += delegate(object obj, SqlInfoMessageEventArgs err)
{
ab = "\n " + err.Message;
message_richTextBox.Text += (ab);
};
cmd.CommandText = #"execute my_sp ";
cmd.ExecuteNonQuery();
con.FireInfoMessageEventOnUserErrors = false;
Problem:
My problem is that I don't get all SQL messgaes as in SQL Server 2008 (image attached) in C#
Some of those are not 'messages' (ie. TDS ERRROR and INFO Messages) but instead are rowcounts. SSMS displays them in the output in a similar manner to Info messages, but they're unrelated.
You get them in SqlClient as return values from DML queries. In other words, the int returned by ExecuteNonQuery:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command.
The messages proper, like 'deleting previous signoff', you already know how to get them: SqlConnection.InfoMessage event, just as in your code.
Declare the local variables and assign the messages and affected rowcount to the variables and make select at last.
Use the SQLDataReader to get the messages in C#
DECLARE #sMessage1 AS VARCHAR(100)
DECLARE #sMessage2 AS VARCHAR(100)
DECLARE #sMessage3 AS VARCHAR(100)
DECLARE #sAffectedRows1 AS VARCHAR(100)
DECLARE #sAffectedRows2 AS VARCHAR(100)
DECLARE #sAffectedRows3 AS VARCHAR(100)
SET #sMessage1 = 'something1'
First UPDATE query
SET #sAffectedRows1 = ##ROWCOUNT
SET #sMessage2 = 'something2'
Second UPDATE query
SET #sAffectedRows2 = ##ROWCOUNT
SET #sMessage3 = 'something3'
Third UPDATE query
SET #sAffectedRows3 = ##ROWCOUNT
SELECT #sMessage1 AS Msg1, #sMessage2 AS Msg2, #sMessage3 AS Msg3,
#sAffectedRows1 AS Rows1, #sAffectedRows2 AS Rows2, #sAffectedRows3 AS Rows3
I think SQLConnection will not help you to get those message that you see in SQL Server Management Studio.
To get that message you have to do following thing. ( Main SMO)
Use SQL Server Management Object ( You will find SQL server management object msi on Microsoft Site)
After that include reference of those DLL and use following code.
public static void ExecuteScript(string scriptContent)
{
SqlConnection conn = new SqlConnection(dbConnectionString);
conn.Open();
Server sqlServer = new Server(new Microsoft.SqlServer.Management.Common.ServerConnection(conn));
sqlServer.ConnectionContext.InfoMessage += new SqlInfoMessageEventHandler(ConnectionContext_InfoMessage);
sqlServer.ConnectionContext.ServerMessage += new Microsoft.SqlServer.Management.Common.ServerMessageEventHandler(ConnectionContext_ServerMessage);
sqlServer.ConnectionContext.ExecuteNonQuery(scriptContent);
}
static void ConnectionContext_ServerMessage(object sender, Microsoft.SqlServer.Management.Common.ServerMessageEventArgs e)
{
Console.WriteLine("Method : ConnectionContext_ServerMessage" + System.Environment.NewLine + e.Error.Message + System.Environment.NewLine);
}
static void ConnectionContext_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
Console.WriteLine(System.Environment.NewLine + e.Message + System.Environment.NewLine);
}
Related
Little bit of background of my Application.
I am working on a File Watcher windows service using C# that looks for .bak files in a particular folder and then use it to restore the database that file belongs to.
The Restored Database has a Stored Procedure that calls 10 different stored procedure. It's the File Watcher's functionality to execute the stored procedure after the Restore is done.
The Stored Procedure is [1_IMPORT_DATA_AND_PROCESS_ALL] which calls 10 different stored procedure within itself.
This is the Method which is executing the Stored Procedure after the restore is complete.
// Trigger Stored Procedure after restore.
private void triggerSP(String connectionStr)
{
// This doesn't open the Connection. conn.Open() has to be explicitly called.
SqlConnection conn = new SqlConnection(connectionStr);
try
{
conn.Open();
conn.FireInfoMessageEventOnUserErrors = true;
// Capture messages returned by SQL Server.
conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
{
message += " -> " + e.Message + " -> ";
};
//conn.InfoMessage += new SqlInfoMessageEventHandler(cn_InfoMessage);
//.create a command object identifying the stored procedure.
SqlCommand cmd = new SqlCommand("[dbo].[1_IMPORT_DATA_AND_PROCESS_ALL]", conn);
cmd.CommandTimeout = 0;
// 2. set the command object so it knows to execute a stored procedure.
cmd.CommandType = CommandType.StoredProcedure;
// Add a check here as well.
// execute the command.
SqlDataReader rdr = cmd.ExecuteReader();
string[] info = new string[] { "Message: \n" + message };
WriteToFile(info);
// Since we are not using - using block we have to explicitly call Close() to close the connection.
conn.Close();
}
catch (SqlException SqlEx){
string[] error = new string[3] ;
string msg1 = "Errors Count:" + SqlEx.Errors.Count;
string msg2 = null;
foreach (SqlError myError in SqlEx.Errors)
msg2 += myError.Number + " - " + myError.Message + "/" ;
conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
{
message += "\n" + e.Message;
};
error[0] = msg1;
error[1] = msg2;
error[2] = message;
WriteToFile(error);
}
finally
{
//call this if exception occurs or not
//in this example, dispose the WebClient
conn.Close();
}
}
Problem
I am only getting back the Message outputs from the very first stored procedure i.e [1_IMPORT_DATA_AND_PROCESS_ALL] and not from the stored procedure which are being called from within [1_IMPORT_DATA_AND_PROCESS_ALL] as shown bellow.
As soon as the 1st Sp calls another SP my codes stops reading the Messages.
I want to capture all the Messages that are being printed, something Like this (image below), which are the actual messages that are being printed when I execute the SP in SSMS.
This particular line is fetching the Messages from the SP
conn.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
{
message += " -> " + e.Message + " -> ";
};
So far I have referred to everything form this question and it's derivatives.
I can't change the Stored Procedure now, I can only make changes to my C# Application.
Hope my question is clear.
Good day,
Note! This message is not marked as "community wiki" and as such it written by a specific person under his name and this is not a shared article. If you have comments then please use the comments instead of changing the content, which the OP meant to provide (for example extra learning points in the content). Thanks!
In the following script I present an example of handling nested Stored Procedure error.The basic Idea is to use TRY/CATCH in order to prevent raising the error and stop the transaction, and the OUTPUT is used to return the error information to the upper level SP
This is only a basic example...
CREATE or ALTER PROCEDURE L1 (
#InputInt int,
#ErrMessage NVARCHAR(MAX) OUTPUT,
#ErrNum INT OUTPUT
)AS
SELECT ##NESTLEVEL AS 'Inner Level'; -- this information present the level of the SP during the execution. It is not needed for the solution but for the sake of the learning and understanding of nested SP
Select 'Start L1'
BEGIN TRY
-- When the ionput is 0 we Generate a divide-by-zero error.
SELECT 1/#InputInt;
END TRY
BEGIN CATCH
SET #ErrMessage = ERROR_MESSAGE()
SELECT #ErrMessage
END CATCH;
SET #ErrNum = ##ERROR
IF (#ErrNum > 0) Begin
SELECT 'L1 error Number: ' + CONVERT(NVARCHAR(10), #ErrNum)
Return
END
ELSE
select 'L1 OK'
GO
CREATE or ALTER PROCEDURE L2 (
#InputInt int
) AS
Declare #ErrMessage NVARCHAR(MAX) = '', #ErrNum INT = 0
SELECT ##NESTLEVEL AS 'Outer Level';
BEGIN TRY
EXEC L1 #InputInt, #ErrMessage, #ErrNum;
END TRY
BEGIN CATCH
SELECT 'There was error!'
select ##ERROR
END CATCH
GO
EXECUTE L2 1 -- OK
GO
EXECUTE L2 0; --Raise error in the nested stored procedures
GO
I'm attempting to add the finishing touch to a project I've been working on and am currently trying to modify a feature that I've created. The feature being that if a student has completed an examination, they are able to view the results. However, what I want to do is create an if else statement that is essentially: if the exam has been taken and completed, then they are redirected to the page that shows them the specific exam's results. Else, it returns a message at the top of the page stating "This examination has not been completed yet."
The current code I have (which is operated through a button on the page) is:
protected void btnViewPrevExam_Click(object sender, EventArgs e)
{
Session["intExaminationID"] = ddlExamination.SelectedValue;
Int32 int32StudentID = Convert.ToInt32(Session["StudentID"]);
Session["int32StudentID"] = Convert.ToInt32(int32StudentID);
// Define the ADO.NET connection object.
SqlConnection objSqlConnection = new SqlConnection(WebConfigurationManager.ConnectionStrings["OPT"].ConnectionString);
// Develop the SQL call.
// Develop the SQL call.
String strSQL = "";
strSQL = "SELECT AnswerID, Question, OptionA, OptionB, OptionC, OptionD, CorrectAnswer, Answer ";
strSQL += " FROM Question, Answer, Examination, Student ";
strSQL += " WHERE Examination.ExaminationID = " + ddlExamination.SelectedValue;
strSQL += " AND Student.StudentID = " + int32StudentID;
strSQL += " AND Answer.QuestionID = Question.QuestionID ";
strSQL += " AND Answer.StudentID = Student.StudentID ";
strSQL += " AND Examination.ExaminationID = Question.ExaminationID ";
// Create the SQL command object.
SqlCommand objSqlCommand = new SqlCommand(strSQL, objSqlConnection);
// Retrieve the row from the table.
objSqlConnection.Open();
SqlDataReader objSqlDataReader = objSqlCommand.ExecuteReader();
objSqlDataReader.Read();
if (strSQL != null)
{
objSqlDataReader.Close();
objSqlConnection.Close();
Response.Redirect("StudentExamResults.aspx");
}
else
{
this.Master.MessageForeColor = System.Drawing.Color.Red;
this.Master.Message = "The selected examination has not been completed.";
}
}
What this button does currently is that it will send the student to the examination results page regardless if the examination has been completed or not. This is due to the line "if (strSQL != null)" and it never being null because the SQL call has been made and filled. I've attempted other ideas, as well as performing a objSqlDataReader for the AnswerID but it didn't work properly. This is a small extra feature I'd like to add to this project that I thought of and would be very pleased if I could find some help on sorting out what I'm doing wrong. Thank you in advance!
Testing if strSQL is not null will always succeed because you are setting it to a non-null value earlier in the method.
To see if a record already exists for a previously-completed examination, you need to check the return value of the call to objSqlDataReader.Read(); it will return true as long as there are additional rows (or, in this case, a first row) to consume from your SELECT query. Thus, change this...
objSqlDataReader.Read();
if (strSQL != null)
{
...to this...
if (objSqlDataReader.Read())
{
As an additional note, consider wrapping objSqlConnection, objSqlCommand, and objSqlDataReader in using blocks to ensure they are properly closed/disposed. As it is now, you are not closing objSqlDataReader and objSqlConnection when the exam needs to be completed, and objSqlCommand is not disposed at all. objSqlDataReader would then be closed as follows, regardless of which branch of the if is taken...
using (SqlDataReader objSqlDataReader = objSqlCommand.ExecuteReader())
{
if (objSqlDataReader.Read())
{
//objSqlDataReader.Close();// No longer necessary - handled by using
objSqlConnection.Close();
Response.Redirect("StudentExamResults.aspx");
}
else
{
this.Master.MessageForeColor = System.Drawing.Color.Red;
this.Master.Message = "The selected examination has not been completed.";
}
}
Assuming you don't care about the contents, rather you just want to check if the row exists, you can do something like this:
string sql = "SELECT COUNT(AnswerID) FROM Question ........ WHERE ......";
using (var connection = CreateConnection()) {
using (var cmd = new SqlCommand(sql, connection)) {
bool exists = (int) cmd.ExecuteScalar() > 0;
if (exists) {
Response.Redirect("StudentExamResults.aspx");
} else {
// Do the other thing
}
}
}
The Situation: I am creating an automated task which queries MySQL (through ODBC) and inserts the result set to a MS Access Database (.mdb) using OLEDB.
The Code:
OleDbConnection accCon = new OleDbConnection();
OdbcCommand mySQLCon = new OdbcCommand();
try
{
//connect to mysql
Connect();
mySQLCon.Connection = connection;
//connect to access
accCon.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;" +
#"Data source= " + pathToAccess;
accCon.Open();
var cnt = 0;
while (cnt < 5)
{
if (accCon.State == ConnectionState.Open)
break;
cnt++;
System.Threading.Thread.Sleep(50);
}
if (cnt == 5)
{
ToolBox.logThis("Connection to Access DB did not open. Exit Process");
return;
}
} catch (Exception e)
{
ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
}
OleDbCommand accCmn = new OleDbCommand();
accCmn.Connection = accCon;
//access insert query structure
var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
foreach (var table in tblNQuery)
{
try
{
mySQLCon.CommandText = table.Value;
//executed mysql query
using (var dataReader = mySQLCon.ExecuteReader())
{
//variable to hold row data
var rowData = new object[dataReader.FieldCount];
var parameters = "";
//read the result set from mysql query
while (dataReader.Read())
{
//fill rowData with the row values
dataReader.GetValues(rowData);
//build the parameters for insert query
for (var i = 0; i < dataReader.FieldCount; i++)
parameters += "'" + rowData[i] + "',";
parameters = parameters.TrimEnd(',');
//insert to access
accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
try
{
accCmn.ExecuteNonQuery();
}
catch (Exception exc)
{
ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message + "\\n\\tInsert query -> " + accCmn.CommandText );
}
parameters = "";
}
}
}
catch (Exception e)
{
ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
}
}
Disconnect();
accCmn.Dispose();
accCon.Close();
The Issues:
The memory usage goes very high (300MB++) while the MS Access file size does not change constantly! Seems like the insert caches the data rather that saving it to disk.
It is very slow! I know my query executes within a few second but rather insertion process takes long.
I have tried using prepared statement in MS Access and insert the values as parameters instead of string concat to create insert query. However I get this exception message:
Data type mismatch in criteria expression.
Anyone know how to fix this or have a better approach?
You could create a VBA macro that uses the DoCmd.TransferDatabase method to pull data through ODBC into your Access database. It would probably be much faster and simpler as well.
To run the VBA code from an external program or scheduled task, simply initiate Access to open your file with the /x command line switch and it will run the import macro on startup. A GB of data though is still going to take a while. I found an article by David Catriel that implemented this approach.
An even better option is to use a different database engine back-end like the free version of SQL Server Express. Then you have a lot more options and it is much more robust. If you need MS Access forms and reports, you can create an ADP project file if you use SQL Server, or you can use linked tables to get at your data. You could even use Access as a front-end to your MySQL database instead of copying all the data if that would satisfy your requirements.
Instead of writing code, you could turn to SQL Server Integration Services (SSIS), and be done before lunch. It is available as an extension to Visual Studio, in case you do not have it on your computer already with SQL Server.
With SSIS you are able to create a reusable SSIS package that can be triggered from the command line or scheduled task. This guide shows how to pull data from MySQL into SQL Server, but the SQL Server part should be easy to replace with Access.
some changes with comment to add transaction for command execution. if transactions is not controlled manually, it will be created and committed every time automatically and it's a time consuming action
OleDbConnection accCon = new OleDbConnection();
OdbcCommand mySQLCon = new OdbcCommand();
try
{
//connect to mysql
Connect();
mySQLCon.Connection = connection;
//connect to access
accCon.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;" +
#"Data source= " + pathToAccess;
accCon.Open();
var cnt = 0;
while (cnt < 5)
{
if (accCon.State == ConnectionState.Open)
break;
cnt++;
System.Threading.Thread.Sleep(50);
}
if (cnt == 5)
{
ToolBox.logThis("Connection to Access DB did not open. Exit Process");
return;
}
}
catch (Exception e)
{
ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
}
//AMK: transaction starts here
var transaction = accCon.BeginTransaction();
OleDbCommand accCmn = new OleDbCommand();
accCmn.Connection = accCon;
accCmn.Transaction = transaction;
//access insert query structure
var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
foreach (var table in tblNQuery)
{
try
{
mySQLCon.CommandText = table.Value;
//executed mysql query
using (var dataReader = mySQLCon.ExecuteReader())
{
//variable to hold row data
var rowData = new object[dataReader.FieldCount];
var parameters = "";
//read the result set from mysql query
while (dataReader.Read())
{
//fill rowData with the row values
dataReader.GetValues(rowData);
//build the parameters for insert query
for (var i = 0; i < dataReader.FieldCount; i++)
parameters += "'" + rowData[i] + "',";
parameters = parameters.TrimEnd(',');
//insert to access
accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
try
{
accCmn.ExecuteNonQuery();
}
catch (Exception exc)
{
ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message +
"\\n\\tInsert query -> " + accCmn.CommandText);
}
parameters = "";
}
}
//AMK: transaction commits here if every thing is going well
transaction.Commit();
}
catch (Exception e)
{
ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
//AMK: transaction rollback here if there is a problem
transaction.Rollback();
}
}
Disconnect();
accCmn.Dispose();
accCon.Close();
Create a DSN (data source name) for the SQL server database. Then select that DSN by opening the Microsoft Access database and choosing to import from that DSN. You should have the ability to import that exact 1GB table (schema, data, everything).
More information on using a DSN:
https://support.office.com/en-us/article/Link-to-SQL-Server-data-0474c16d-a473-4458-9cf7-f369b78d3db8
Alternatively you can just link to the SQL server database (not import to an Access table) using that DSN and skip the import altogether.
Should the INSERT be part of a TRANSACTION. Being within a TRANSACTION usually speeds BULK INSERTS
Thanks everyone for the answers. I just found the main problem in my code. The reason for heavy memory usage (issue #1) was ODBC was caching the data from MySQL regardless of C# approach (DataReader). That issue is resolved by checking the Don't cache results of forward-only cursors checkbox in DSN settings. This also made the process slightly faster (30%). However, more concrete approach is still what Brian Pressler and Egil Hansen suggested.But since they require software installation and/or migration plan, easiest way would be to stick to this piece of code.
I've a form opened which is has loaded some sort of data (like username, CNIC, Contact no, etc etc) in Check boxes, now I want to update the data in such manner that I simply change the text in the text boxes and click on the save changes to save it. I've tried it but I am not able to do it in correct manner.
Let me show you how I've coded, the code I did in frmViewformList savechanges button is :
private void btnSaveChanges_Click(object sender, EventArgs e)
{
string sql;
string UserName;
UserName = txtUserName.Text; // saving data loaded on run time to UserName
sql = "";
sql += "UPDATE UserLogin";
sql += "SET Name = "+ //how to access data I've changed in TextBox after loading +"";
sql += "WHERE Name= " + //how to access data which was in text box right after loading + ""; //
}
I am a bit confused about how to refer to data, like the name already in the text box or the name which I have changed and how to write it in SQL query...
This question is a bit confusing, I know. Let me explain; the form is loaded, there are text boxes which is being populated with the data in database on load event, I change the data in text boxes and save on click so that the update query runs and changes the data in database as well.
I'm not able to create logic here how to do this, can any one help me out, I am sorry I am a new developer of C# that's why I am a bit confused.
You should use Sql Parameters in order to avoid SQL Injection which could leave your database vulnerable to malicious exploitation.
It's a good idea to separate the logic for performing the update to the logic where you create your query so you don't have to repeat code and so that you can maintain your code easier.
Here is an example you can reference:
public void DoWork()
{
// Build Query Use #Name Parameters instead of direct values to prevent SQL Injection
StringBuilder sql = new StringBuilder();
sql.Append("UPDATE UserLogin");
sql.Append("SET Name = #UpdatedName");
sql.Append("WHERE Name = #Name");
// Create parameters with the value you want to pass to SQL
SqlParameter name = new SqlParameter("#Name", "whatEverOldNameWas");
SqlParameter updatedName = new SqlParameter("#UpdatedName", txtUserName.Text);
Update(sql.ToString(), new [] { name, updatedName });
}
private static readonly string connectionString = "Your connection string"
private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
public static int Update(string sql, SqlParameter[] parameters)
{
try
{
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandText = sql;
foreach (var parameter in parameters)
{
if (parameter != null)
command.Parameters.Add(parameter);
}
connection.Open();
return command.ExecuteNonQuery();
}
}
}
catch (Exception)
{
throw;
}
}
You will want to strip all ', ", and ` characters out of your input so that people can't inject SQL. When you do SET Name = " +, you'll want to actually wrap whatever you're including in quotes because it's a string: SET Name = '" + UserName "' " +...
This is probably best done using
string.Format("UPDATE UserLogin SET Name = '{0}' WHERE Name = '{1}'", UserName, FormerUserName);
Then you will execute your query by using System.Data.SqlClient; and then work with SqlConnection to establish a connection to the server, and execute a SqlCommand of some kind; take a look at: http://www.codeproject.com/Articles/4416/Beginners-guide-to-accessing-SQL-Server-through-C
The following is a code snippet to insert data into database using ADO.NET and assuming SQL Server database.
At the top of your .cs file you should have.
using System.Data.SqlClient; // for sql server for other data bases you should use OleClient instead.
And inside your button click event you could put the following.
// to know how to get the right connection string please check this site: http://www.connectionstrings.com
string connString = "database connection string here";
using (SqlConnection con = new SqlConnection(connString))
{
con.Open();
//insert text into db
string sql_insert = "INSERT INTO ....."; // Use parameters here.
SqlCommand cmd_insert = new SqlCommand(sql_insert, con);
int rowsAffected = cmd_insert.ExecuteNonQuery();
}
Hopefully this is enough to get you started.
I have written a simple stored procedure for updating a record which isn't working but I can't work out why. No exceptions are thrown but the record doesn't update either.
See code below:
public int IMGId;
protected void btnUpdate_Click(object sender, EventArgs e)
{
string result = "";
string sSQL = "usp_imageloader_update";
using (SqlConnection dbConnection = new SqlConnection(CKS_app_settings.sql_conn_string_db))
{
// SqlTransaction tn=null;
try
{
dbConnection.Open();
//start Transaction
// tn = dbConnection.BeginTransaction();
SqlCommand command = new SqlCommand(sSQL, dbConnection);
//command.Transaction = tn;
command.CommandText = sSQL;
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 1024;
command.Parameters.AddWithValue("#p_image_id", IMGId);
command.Parameters.AddWithValue("#p_url", txtUrl.Text);
command.Parameters.AddWithValue("#p_alt_text", txtAlt.Text);
//command.Parameters.AddWithValue("#p_filepath", File1.Value);
//command.Parameters.AddWithValue("#p_cntr_id", str_id);
int rowsAffected = command.ExecuteNonQuery();
}
catch (SqlException ex)
{
// throw ex;
//If it failed for whatever reason, rollback the //transaction
//tn.Rollback();
//No need to throw because we are at a top level call and //nothing is handling exceptions
result = ex.InnerException.Message;
}
}
Stored procedure in SQL SERVER
USE [smsdb_test_griffin2]
GO
/****** Object: StoredProcedure [dbo].[usp_imageloader_update] Script Date: 01/04/2012 09:05:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[usp_imageloader_update]
#p_image_id INT,
#p_url VARCHAR(255),
#p_alt_text VARCHAR(255)
as
UPDATE Image_Library_UK
SET
Url=#p_url,
Alt_text=#p_alt_text
WHERE Image_id=#p_image_id
Having tried it in isolation, assuming that this works ( and there is nothing glaringly obvious wrong ), I would assume that one of your parameters is not being set correctly. It could be that the IMGid is not right - which would have this effect - or it coudl be that the the url and alttext have already be reset to their values by the load of the page.
Check the values at the point of calling. It may be you need to use !Page.IsPostBack to not reset these values on a postback. It may be that you need to access them using the request variable - it does depend on the rest of your code.