I created the following stored procedure. It inserts a row into the
Headlines table. If it fails, it returns -1 with the error that sql server
returned. So far, everything seems to be working right except the rollback
part. Is there any reason why the rollback fails?
[code]
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Transactions;
public partial class StoredProcedures {
[Microsoft.SqlServer.Server.SqlProcedure]
public static void InsertHeadline(string Title, string Description, string
Content, DateTime StartDate, DateTime EndDate) {
string SqlQuery = "INSERT INTO Headlines (HeadlineTitle,
HeadlineDescription, HeadlineContent, HeadlineStartDate, HeadlineEndDate)
values (@HeadlineTitle, @HeadlineDescription, @HeadlineContent,
@HeadlineStartDate, @HeadlineEndDate)";
try {
using(TransactionScope Scope = new TransactionScope()) {
using(SqlConnection Connection = new SqlConnection("context
connection=true")){
SqlCommand Command = new SqlCommand(SqlQuery, Connection);
#region Command parameters
Command.Parameters.Add("@HeadlineTitle", DbType.String);
Command.Parameters["@HeadlineTitle"].Value = Title;
Command.Parameters.Add("@HeadlineDescription", DbType.String);
Command.Parameters["@HeadlineDescription"].Value = Description;
Command.Parameters.Add("@HeadlineContent", DbType.String);
Command.Parameters["@HeadlineContent"].Value = Content;
Command.Parameters.Add("@HeadlineStartDate", DbType.Date);
Command.Parameters["@HeadlineStartDate"].Value = StartDate;
Command.Parameters.Add("@HeadlineEndDate", DbType.Date);
Command.Parameters["@HeadlineEndDate"].Value = EndDate;
#endregion
Connection.Open();
Command.ExecuteNonQuery();
} //end connection.
Scope.Complete();
} //end transaction.
} catch(Exception ex) {
using(SqlConnection Connection = new SqlConnection("context
connection=true")) {
Connection.Open();
SqlCommand Command = new SqlCommand("SELECT -1, @ErrorMessage", Connection);
Command.Parameters.Add("@ErrorMessage", DbType.String);
Command.Parameters["@ErrorMessage"].Value = ex.Message;
SqlContext.Pipe.ExecuteAndSend(Command);
}
}
}
};
|
|
0
|
|
|
|
Reply
|
Andy
|
3/12/2010 3:04:58 PM |
|
On Mar 12, 5:04=A0pm, "Andy B." <a_bo...@sbcglobal.net> wrote:
> I created the following stored procedure. It inserts a row into the
> Headlines table. If it fails, it returns -1 with the error that sql serve=
r
> returned. So far, everything seems to be working right except the rollbac=
k
> part. Is there any reason why the rollback fails?
I have no idea. But CLR is weird--you ever look at what goes on
behind the scenes? More than meets the eye. It's almost like they
have a automatic parallel thread generator--I'm always surprised at
the temporary variables that seem to get created. Maybe something is
out of sync so that when you think there should be a rollback, the CLR
engine is in fact 'behind the times' or 'ahead of time' from where you
think it is, and hence the database (which runs on its own clock, so
to speak) never gets affected.
That's the only thing I can think of without a line by line dissection
of your code. BTW I am not a db expert though I do have a pretty good
handle on it.
RL
|
|
0
|
|
|
|
Reply
|
RayLopez99
|
3/12/2010 3:33:43 PM
|
|
"Andy B." wrote:
> I created the following stored procedure. It inserts a row into the
> Headlines table. If it fails, it returns -1 with the error that sql server
> returned. So far, everything seems to be working right except the rollback
> part. Is there any reason why the rollback fails?
>
Maybe you need to use nested Using(s) like this.
using(TransactionScope Scope = new TransactionScope())
using(SqlConnection Connection = new SqlConnection("context
connection=true"))
try
{
conn.open();
other statemants
scope.complete
}
catch
{
}
finally
{
if(conn.State == conn.Open)
conn.close();
}
What that stuff you have about going back to get SQL to get some exception
is what? It doesn't seem to make any sense.
|
|
0
|
|
|
|
Reply
|
Utf
|
3/12/2010 4:37:02 PM
|
|
>What that stuff you have about going back to get SQL to get some exception
>is what? It doesn't seem to make any sense.
1. I need to return the HeadlineID of the headline just inserted (if it was
successful) as well as a "Your headline was successfully saved." message.
This part wasn't included in the stored proc for now. The other part was in
case the insert failed and a rollback happened. It seemed to be the easiest
way of making a resultset for the -1 and the exception text. Do you have any
easier way to work it out? If there was an easy way to create a .net
resultset I would do it.
|
|
0
|
|
|
|
Reply
|
Andy
|
3/12/2010 4:52:19 PM
|
|
"Andy B." <a_borka@sbcglobal.net> wrote in message
news:ewhoYRgwKHA.5812@TK2MSFTNGP02.phx.gbl...
> >What that stuff you have about going back to get SQL to get some
> >exception is what? It doesn't seem to make any sense.
> 1. I need to return the HeadlineID of the headline just inserted (if it
> was successful) as well as a "Your headline was successfully saved."
> message. This part wasn't included in the stored proc for now. The other
> part was in case the insert failed and a rollback happened. It seemed to
> be the easiest way of making a resultset for the -1 and the exception
> text. Do you have any easier way to work it out? If there was an easy way
> to create a .net resultset I would do it.
>
Ok. I reworked the stored proc again. It now doesn't go to the database for
error handling, just sends the error results to the client. Everything still
works fine, but the rollback still fails to execute. Any ideas? Here is the
complete stored proc code.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Transactions;
public partial class StoredProcedures {
[Microsoft.SqlServer.Server.SqlProcedure]
public static void InsertHeadline(string Title, string Description, string
Content, DateTime StartDate, DateTime EndDate) {
string SqlQuery = "INSERT INTO Headlines (HeadlineTitle,
HeadlineDescription, HeadlineContent, HeadlineStartDate, HeadlineEndDate)
values (@HeadlineTitle, @HeadlineDescription, @HeadlineContent,
@HeadlineStartDate, @HeadlineEndDate)";
using(SqlConnection Connection = new SqlConnection("context
connection=true")){
SqlCommand InsertCommand = new SqlCommand(SqlQuery, Connection);
#region InsertCommand parameters
InsertCommand.Parameters.Add("@HeadlineTitle", DbType.String);
InsertCommand.Parameters["@HeadlineTitle"].Value = Title;
InsertCommand.Parameters.Add("@HeadlineDescription", DbType.String);
InsertCommand.Parameters["@HeadlineDescription"].Value = Description;
InsertCommand.Parameters.Add("@HeadlineContent", DbType.String);
InsertCommand.Parameters["@HeadlineContent"].Value = Content;
InsertCommand.Parameters.Add("@HeadlineStartDate", DbType.Date);
InsertCommand.Parameters["@HeadlineStartDate"].Value = StartDate;
InsertCommand.Parameters.Add("@HeadlineEndDate", DbType.Date);
InsertCommand.Parameters["@HeadlineEndDate"].Value = EndDate;
#endregion
SqlTransaction InsertTransaction;
Connection.Open();
InsertTransaction=Connection.BeginTransaction("Insert");
InsertCommand.Connection=Connection;
InsertCommand.Transaction=InsertTransaction;
try {
InsertCommand.ExecuteNonQuery();
InsertTransaction.Commit();
} catch(Exception ex) {
//Handle any commit errors.
SqlDataRecord InsertError = new SqlDataRecord(new SqlMetaData[]
{ new SqlMetaData("ID", SqlDbType.Int),
new SqlMetaData("Message", SqlDbType.NVarChar, 2048) });
InsertError.SetInt32(0, -1);
InsertError.SetString(1, ex.Message);
try {
InsertTransaction.Rollback();
SqlContext.Pipe.Send(InsertError);
} catch(Exception ex2) {
//Deal with rollback errors.
InsertError.SetString(1, ex2.Message);
SqlContext.Pipe.Send(InsertError);
}
}
}
}
};
|
|
0
|
|
|
|
Reply
|
Andy
|
3/12/2010 6:18:37 PM
|
|
> Ok. I reworked the stored proc again. It now doesn't go to the database for
> error handling, just sends the error results to the client. Everything still
> works fine, but the rollback still fails to execute. Any ideas? Here is the
> complete stored proc code.
>
Is not the statement below suppose to be the first line in the Catch of the
first Try/Catch?
InsertTransaction.Rollback();
What does the second Try/Catch have anything to do with the first Try/Catch
and what happened there and rollback of transaction?
You ran the stop sign it seems and started executing other SQL statements
that have nothing to do with what happened in the first Try/Catch from a
logical standpoint.
And you have the rollback in the wrong Try/Catch, which means it blew it off
and committed the changes it sems well before it got to the rollback
statement.
|
|
0
|
|
|
|
Reply
|
Utf
|
3/12/2010 8:14:02 PM
|
|
"Mr. Arnold" <No@No.com> wrote in message
news:0A00CD47-EE9E-4F72-B834-D9003EC25C17@microsoft.com...
>
>
>> Ok. I reworked the stored proc again. It now doesn't go to the database
>> for
>> error handling, just sends the error results to the client. Everything
>> still
>> works fine, but the rollback still fails to execute. Any ideas? Here is
>> the
>> complete stored proc code.
>>
>
> Is not the statement below suppose to be the first line in the Catch of
> the
> first Try/Catch?
>
> InsertTransaction.Rollback();
Probably, but if you have to do error handeling (i.e. log an exception, or
send it to the client) you need to trap the exception before you do a
rollback. If you don't, you lose everything since rollback resets everything
back to default state: The number of commits is set to 0, the number of
commitable statements is set to 0, all references to error codes are set to
null and all exceptions get thrown out the window and are set to null. This
is the same way in transact-sql statements. Consider the following code:
create procedure TestTransaction
as
-- create a transaction
begin try
begin transaction
insert into ATableOfSomeKind (ID, Message) values(0, 'This might work...');
commit transaction
end try
begin catch
-- will send a message to the client if the insert above fails for some
reason.
print error_message()
-- rollback now that there is an uncommitable transaction somewhere.
rollback
-- Just for kicks, try to resend the error again. It should fail.
print error_message()
end catch
--end transact-sql
The above transact-sql is a basic example of what my clr proc was trying to
model after, but it isn't working for some strange reason. You would think
CLR would follow the same rules as transact-sql does...
> What does the second Try/Catch have anything to do with the first
> Try/Catch
> and what happened there and rollback of transaction?
Unless Microsoft is totally clueless and
1. Was born yesterday, and
2. Crawled out from a rock in the desert
They must not know how to write code for their own server. At this link:
http://msdn.microsoft.com/en-us/library/2k2hy99x(VS.71).aspx
It explains how to do the same thing I want to do but with error reporting
to the client in a controlled way. The answer to the next questions are in
that sample.
> You ran the stop sign it seems and started executing other SQL statements
> that have nothing to do with what happened in the first Try/Catch from a
> logical standpoint.
>
> And you have the rollback in the wrong Try/Catch, which means it blew it
> off
> and committed the changes it sems well before it got to the rollback
> statement.
>
>
>
I can try working it out again, but the try...catch inside the first catch
block was Microsoft's idea (see above). I guess it's supposed to deal with
errors in case rollback fails.
|
|
0
|
|
|
|
Reply
|
Andy
|
3/13/2010 1:14:31 AM
|
|
Andy B. wrote:
>
> I can try working it out again, but the try...catch inside the first catch
> block was Microsoft's idea (see above). I guess it's supposed to deal with
> errors in case rollback fails.
>
>
The example link you supplied.
What I see here is a Try/Catch with the rollback in the first Try as the
first thing done on the caught exception, like I said. What are you seeing?
Try
myCommand.CommandText = "Insert into Region (RegionID,
RegionDescription) VALUES (100, 'Description')"
myCommand.ExecuteNonQuery()
myCommand.CommandText = "Insert into Region (RegionID,
RegionDescription) VALUES (101, 'Description')"
myCommand.ExecuteNonQuery()
myTrans.Commit()
Console.WriteLine("Both records are written to database.")
Catch e As Exception
Try
myTrans.Rollback()
Catch ex As SqlException
If Not myTrans.Connection Is Nothing Then
Console.WriteLine("An exception of type
Where is this CLR example? Are you trying to roll your own with two
examples combining the two on a pillage and plunder?
|
|
0
|
|
|
|
Reply
|
Mr
|
3/13/2010 3:24:12 AM
|
|
Andy B. wrote:
<snipped>
What I suggest you do is rework the code for now doing a divideByZero in
code before the commit. In the catch, there should only be one statement
in the catch the rollback -- no try in the catch no nothing.
You can do it with the Using Transcope too and let it rollback.
I suggest that you see it in its simplistic example to know that it will
work the -- rollback.
Then I suggest that you sit back and ponder this. What are you doing in
the code that leads to the rollback not working and the trans is
committed, even after it blew-up?
|
|
0
|
|
|
|
Reply
|
Mr
|
3/13/2010 3:55:08 AM
|
|
|
8 Replies
324 Views
(page loaded in 0.186 seconds)
|