C#
复制
// 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);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
注解
如果确信范围内的所有操作都已成功完成,则只应调用此方法一次,以通知事务管理器所有资源的状态都是一致的,并且可以提交事务。 最好将调用作为块中的 using 最后一个语句。
未能调用此方法会中止事务,因为事务管理器将此解释为系统故障或在事务范围内引发的异常。 但是,还应注意,调用此方法并不能保证事务的提交。 它只是一种将状态通知给事务管理器的方式。 调用此方法后,无法再通过 Current 属性访问环境事务,并且尝试这样做会导致引发异常。
如果 TransactionScope 对象创建了事务,则资源管理器之间的实际提交工作将发生在 End Using 语句中。 如果该对象未创建事务,则每当 Commit 对象的所有者调用 CommittableTransaction 时都会执行提交。 此时,事务管理器会调用资源管理器,并根据是否在 对象上 TransactionScope 调用此方法来通知它们提交或回滚。
public readonly struct Range : IEquatable<Range>
{
public Index Start { get; }
public Index End { get; }
public Range(Index start, Index end)
{
this.Start = start;
this.End = end;
}
public ValueTuple<int, int> GetOffsetAndLength(int length)
{
Index start = this.Start;
int num;
if (start.IsFromEnd)
{
num = length - start.Value;
}
else
{
num = start.Value;
}
Index end = this.End;
int num2;
if (end.IsFromEnd)
{
num2 = length - end.Value;
}
else
{
num2 = end.Value;
}
return new ValueTuple<int, int>(num, num2 - num);
}
}
public int GetGBS(int num1, int num2)
{
int temp, a, b;
if (num1 < num2)
{
temp = num1;
num1 = num2;
num2 = temp;
}
a = num1;
b = num2;
while (b != 0)
{
temp = a % b;
a = b;
b = temp;
}
return num1 * num2 / a;
}