如何锁定并发用户访问与数据库中的数据相关的页面

时间:2013-10-28 23:32:15

标签: c# asp.net sql-server locking

我有一个用C#.NET编写的应用程序,用户输入,编辑和删除访问使用SQL Server创建的数据库的事件。应用程序使用搜索页面将搜索查询中的各行填充到数据网格中,然后一旦选择,用户就可以按下更新按钮,而更新按钮又转到另一个页面,其中数据被填充到一个表格中进行编辑,这是我的问题在哪里。我正在尝试实现一种锁定机制,以便当用户从数据库访问一行时,另一个用户将无法启动同一页面。目前我已经为页面调用的每个存储过程实现了几个事务,这些事务可以解决这个问题,但是,当页面加载时,每个存储过程都被单独调用,然后在填充数据后关闭,所以没有办法通过那里锁定。这是我的下一个想法,试图在此特定页面加载时将其锁定到并发用户。填充页面的主存储过程调用IncidentID来检索数据,那么有没有办法检查是否在Page_Load中使用了此ID?我仍处于入门级别,肩膀上有一个巨大的头部,所以我正在通过这里和其他网页学习很多这个实现,但我还没有找到任何帮助......但代码相当冗长但如果您需要参考,请告诉我。 TIA

编辑:这是一些代码。我正在使用SSMS,因此为我添加了分号。这些是测试,但具有确切的语法...... 查询以使用数据填充表单

USE [Test_Live]
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_SelectIncident_ByCaseNumberUpdate]
(
    @IncidentID int
)
AS
BEGIN TRANSACTION
SELECT i.IncidentID,
i.PersonID,
i.BusInfoID,
i.TypeOfIncident,
i.DateOfIncident,
/* etc. etc. */
FROM tblTestIncident i WITH(ROWLOCK)
left JOIN tblTestPerson p on i.PersonID = p.PersonID
/* some other joins are here */
WHERE i.IncidentID = @IncidentID
COMMIT

用数据填充表单的C#代码。 GetConnection()方法位于页面正在使用的另一个.dll文件中。它通过ConfigurationSettings.AppSettings返回连接字符串。

protected void Page_Load(object sender, EventArgs e)
{
    this.gIncidentID = Convert.ToInt32(Utils.decryptQueryString(this.Request.QueryString["iid"]));
    try
    {
        this.lblCurrentUser.Text = this.Page.User.Identity.Name.ToUpper();
    }
    catch (Exception ex)
    {
       this.lblErrors.Text = this.lblErrors.Text + "Unexpected exception in Load: " + ex.Message + ". ";
    }
    this.populateFormWithData(this.gIncidentID);
}

private void populateFormWithData(int incidentID)
{
   SqlConnection connection = this.GetConnection();
   SqlParameter sqlParameter = new SqlParameter("@IncidentID", SqlDbType.Int);
   sqlParameter.Direction = ParameterDirection.Input;
   sqlParameter.Value = (object)incidentID;
   SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
   sqlDataAdapter.SelectCommand = new SqlCommand();
   DataSet dataSet = new DataSet();
   sqlDataAdapter.SelectCommand.Connection = connection;
   sqlDataAdapter.SelectCommand.CommandText = "sp_SelectIncident_ByCaseNumberUpdate";
   sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
   sqlDataAdapter.SelectCommand.Parameters.Add(sqlParameter);
   sqlDataAdapter.Fill(dataSet, "Incident");
   if (dataSet.Tables["Incident"].Rows.Count > 0)
   {
      //code that fills in all fields within the page
   }
   else
   {
      this.lblCaseNumberData.ForeColor.Equals((object)"Red");
      this.lblCaseNumberData.Text = "No Case data found!";
   }
   //this is where I think the problem is as to why the transactions aren't working
   connection.Close();
}

我希望这会有所帮助......

1 个答案:

答案 0 :(得分:1)

像这样锁定数据可能会有问题。用户可以保持页面打开并离开当天。 数据将被锁定,直到它们返回。最好在表中添加TimeStamp列并在更新前检查它是否已更改。如果TimeStamp已更改,请通知用户并重新加载数据。

见这里的例子:

SQL Server optimistic locking - Returning changed timestamp value

TimeStamp / RowVersion信息:

http://msdn.microsoft.com/en-us/library/ms182776%28v=sql.105%29.aspx