System.Transactions 的实际用途是什么?
我看到了 System.Transactions 命名空间,并且想知道,我可以吗实际上用这个命名空间用法创建一个 RDMBS 吗?
但是当我看到一些示例时,我不明白 System.Transactions 除了简单的 try catch 并获取成功/失败结果之外,还如何执行其他操作?
这是 MSDN 网站上的示例,我知道它可能非常简单,但我无法理解此示例的好处,有人可以告诉我以下示例中的简单 try/catch 和事务范围之间有什么区别。
如果我应该创建一个 RDBMS(创建我自己的 RDBMS),我知道我们必须将我们执行的操作的大量日志写入磁盘,最后我们在回滚的情况下撤消这些操作,但这里没有任何内容关于撤消任何事情。
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
writer.WriteLine("ApplicationException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
在上面的例子中,我们要承诺什么?我猜 SQL 客户端库会做所有事情,对吧?这是否意味着 System.IO.StringWriter 将包含所有成功文本或所有失败文本?或者 TransactionScope 的范围之间是否有任何锁定?
I have seen System.Transactions namespace, and wondered, can I actually make a RDMBS with this namespace usage?
But when I saw some examples, I do not understand how System.Transactions does anything beyond simple try catch and getting us success/failure result?
This is the example on MSDN's website, I know it may be very simple but I am unable to understand the benefit in this sample, can someone tell me what is difference between simple try/catch and Transaction scope in this following sample.
If I am supposed to make a RDBMS (create my own RDMBS), I understand we have to write lots of logs to disk of the operations we execute and at the end we undo those operations in the case of rollback, but here there is nothing about undoing anything.
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
writer.WriteLine("ApplicationException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
In above example what are we committing? I guess SQL Client library will do everything right? Does this mean that System.IO.StringWriter will either contain all success text or all failure text? or is there any locking between scope of TransactionScope?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,TransactionScope 与 try/catch 不同。 TransactionScope 是事务的名称范围。范围内的事务必须通过调用范围上的 Complete 来显式提交。任何其他情况(包括范围内引发的异常)都会导致使用块完成,该块会处置范围并隐式回滚未完成的事务,但它不会处理异常。
在基本场景中,来自 System.Transactions 的事务的行为与数据库客户端事务相同。 System.Transactions 提供以下附加功能:
First of all TransactionScope is not the same as try/catch. TransactionScope is by the name scope of a transaction. Transaction in scope has to be explicitly commited by calling Complete on the scope. Any other case (including exception raised in scope) results in finishing using block which disposes the scope and implicitly rollback the incomplete transaction but it will not handle the exception.
In basic scenarios transaction from System.Transactions behaves same as db client transaction. System.Transactions provides following additional features:
事务将为您执行必要的锁定。此外,如果事务未由 Complete() 提交(如注释所建议),则当事务在其范围结束时被处理时,存在隐式回滚。因此,如果出现异常,所有操作都会自动回滚,数据库不会发生任何变化。例如,如果第二个查询失败,它也会使第一个查询的更改被丢弃。
然而,对于 StringWriter,它仍然会包含直到故障点的消息(例如,
在这段代码之后,两者都会出现在您的日志中。
至于使用此类创建 RDBMS,我不确定我是否理解您的问题。如果如果你想真正创建一个关系数据库管理系统,我想说你可能找错地方了,如果你的意思是你想通过事务访问RDBMS,我会说,这取决于你的需求,即是否需要。事务可以保证您的语句将以全有或全无的方式按顺序运行,那么是的,事务是一个很好的起点。
A Transaction will do the necessary locking for you. Also, there is an implicit Rollback, when the transaction is Disposed at the end of its scope if it was not committed by Complete() (as suggested by the comments). So in case there is an exception, all operations are rolled back automatically and no change will take place in the database. For instance, if the second query fails, it will also make the changes of the first query to be discarded.
However for the StringWriter, it will still contain messages up to the point of failure (for example
can both appear in your log after this code.
As for creating an RDBMS with this class, I'm not really sure I understand your question. If you want to actually create a relational dabase management system, I would say you are probably looking at the wrong place. If you mean you want to access an RDBMS via Transaction, I would say, it depends on your needs, ie. if you need Transactions that can guarantee that your statements will run in order and in an all-or-none fashion, then yes, Transaction is a good place to start.