服務操作MyMethod(int id)
從單個數據庫表中檢索特定行(基於參數id
),並且在它返回之前也將該狀態保存回表格。如果兩個呼叫(第一個呼叫在交易T1內發生,而第二個在交易T2內)發生到MyMethod()
,則服務將嘗試同時執行這兩個呼叫。由於T1和T2嘗試訪問相同的數據庫表,兩個事務中的一個將被授予對該資源的訪問權限,而另一個應該被阻止,直到原始事務提交或中止。而是我得到一個異常事務(進程ID 54)已被死鎖的鎖資源與另一個進程,並已被選作死鎖犧牲品以下代碼不會導致死鎖,但我得到的事務(進程ID 54)已死鎖...
我不明白背後,因爲據我可以拋出異常僵局推理告訴我們沒有任何僵局的危險。首先,這兩個事務在不同的行上訪問和操作。爲什麼不是DB數據庫資源才鎖定,直到原始事務提交或中止?
下面是代碼:
[ServiceContract]
public interface IService
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void Process(int id);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults=true)]
public class Service : IService
{
string state_Data = "";
[OperationBehavior(TransactionScopeRequired = true)]
public void Process(int id)
{
GetState(id);
Thread.Sleep(6000);
SaveState(id);
}
private void GetState(int id)
{
using (SqlConnection con = new SqlConnection())
{
con.ConnectionString = "data source=localhost; initial catalog=WCF; integrated security=sspi;";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT * FROM StateTable WHERE id = @id";
cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;
cmd.Connection = con;
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
state_Data = reader["State"].ToString();
}
}
private bool SaveState(int id)
{
using (SqlConnection con = new SqlConnection())
{
con.ConnectionString = "data source = localhost; initial catalog=WCF; integrated security=sspi;";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "UPDATE StateTable SET [email protected] WHERE Id = @id";
cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;
cmd.Parameters.Add("@State", SqlDbType.NVarChar).Value = state_Data;
cmd.Connection = con;
con.Open();
int ret = cmd.ExecuteNonQuery();
return ret == 1;
}
}
}
編輯:
在情況下,這將有所幫助,這裏是客戶端代碼:
第一個客戶:
ServiceClient proxy = new ServiceClient("WSDualHttpBinding_IService");
using (TransactionScope scope = new TransactionScope())
{
proxy.Process(1);
scope.Complete();
}
SECOND客戶:
ServiceClient proxy = new ServiceClient("WSDualHttpBinding_IService");
using (TransactionScope scope = new TransactionScope())
{
proxy.Process(2);
scope.Complete();
}
謝謝
對不起,我沒有注意到你的問題。我不知道任何有關索引,但我懷疑表有任何,因爲創建表的SQL語句沒有指定任何索引 - CREATE TABLE StateTable(id int PRIMARY KEY,狀態nvarchar(100)) – user437291 2011-03-23 21:24:18