C#锁定记录多用户

时间:2014-02-03 14:44:14

标签: c# sql-server

我正在寻找处理多用户访问C#-Sql服务器应用程序的建议。 C#程序从日期为空的表中选择前5行,然后根据用户的输入更新这些记录。如果有多个人正在使用该应用程序,我该如何确保数据保持一致?我正在使用网格控件来显示数据和一个调用SaveToDataBase过程的按钮。这是零件代码

protected void Page_Load(object sender, EventArgs e)
{

    string sqlSel = @" SELECT   TOP 5 r.[keyid], name
                        FROM   db1.Table1 r where date is null  
                        GROUP BY r.keyid, name; ";

    if (!IsPostBack)
    {
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
        {
            connection.Open();
            SqlCommand cmdSel = new SqlCommand(sqlSel, connection);
            SqlDataReader reader1 = cmdSel.ExecuteReader();

            while (reader1.Read())
            {

                DataSet ds = GetData(sqlSel);
                if (ds.Tables.Count > 0)
                {
                    GridView1.DataSource = ds;
                    GridView1.DataBind();
                }
                else
                {
                    Response.Write("Unable to connect to the database.");
                }

            }
            connection.Close();
        }
    }


protected void SaveToDatabase()
{

    string datenow = DateTime.Now.ToString(@"MM\/dd\/yyyy h\:mm tt");
    string sqlUpd = @"UPDATE [db1].[Table1] set DateVerified=@datenow where KeyID=@keyID and name=@name";
    try
    {
        using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString))
        {
            connection.Open();

            SqlCommand cmdUpd = new SqlCommand(sqlUpd, connection);
            cmdUpd.Parameters.Add("@datenow", SqlDbType.DateTime);
            cmdUpd.Parameters["@datenow"].Value = datenow;

            Int32 rowsAffected = 0;
            rowsAffected = cmdUpd.ExecuteNonQuery();

            connection.Close();

}
private DataSet GetData(string cmdSel)
{

    String strConnString = System.Configuration.ConfigurationManager.ConnectionStrings["SQLConnectionString"].ConnectionString;
    DataSet ds = new DataSet();
    try
    {
        SqlConnection con = new SqlConnection(strConnString);
        SqlDataAdapter sda = new SqlDataAdapter(cmdSel, con);
        sda.Fill(ds);

由于 Rashmi

3 个答案:

答案 0 :(得分:1)

您可以使用乐观并发和版本ID之类的内容,每当有人更改行时都应该更新,例如:

//  Table User
create table User(
    Id int primary key, 
    Name varchar(300) not null, 
    Version long not null default 0
);

// the select code
select Id, Name, Version
from User
where Id = ?

// the update code
update User
set
    Name = ?
    Version = Version + 1
where
    Id = ?
    and Version = ?

想象一下,两个用户进入一个屏幕,您可以在其中更新用户名。想象一下您的代码的以下顺序:

UserA:  select Id, Name, Version from User where Id = 1;        // (1, John Doe, 0)
UserB:  select Id, Name, Version from User where Id = 1;        // (1, John Doe, 0)
UserA:  update User set Name = 'Jane Doe' Version = Version + 1 where Id = 1 and Version = 0;   // 1 row updated
UserA:  commit;
UserB:  update User set Name = 'Mr John Doe' Version = Version + 1 where Id = 1 and Version = 0;    // 0 row updated which means someone updated the row
UserB:  rollback;   // you should rollback and send an info to the user that someone changed the information he was seeing (refresh the screen)

使用这种方法可以防止锁定行。每次更新o删除某些内容并且受影响的行数与您预期的不同时,应该应用乐观并发。 大多数ORM框架已经通过使用版本或时间戳实现了这种方法,但逻辑是相同的。请记住,应始终执行版本字段的更新。

你应该知道如何使用这个实际的例子来实现ORM(在这种情况下是实体框架)如何在这里实现这个逻辑:http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application

答案 1 :(得分:0)

有几种不同的方法:

您可以将WHERE条件添加到update语句中。第一个用户更新记录将受到影响 - 行= 5,下一个影响行= 0,因此您知道他的数据无法保存,但必须重新加载(并最终合并)。

或者您可以在获取数据时将记录设置为分配给用户,以便下一个记录获得不同的记录(WHERE (AssignedUser <> @MYUSER))。

如果您真的想要锁定 - 这意味着在第一个用户保存之前,另一个应用程序无法读取前5个记录 - 您可以使用非常严格的IsolationLevel在一个事务中进行读写。

答案 2 :(得分:0)

防止更新分配了日期的值

update table set value = 1, date = getdate() 
where id = 1 and date is null 

如果date为null,我想你会更新0行 所以你可以提供用户反馈

但是一次只有5个问题,因为这会增加碰撞的可能性(日期不为空)

我会有某种类型的锁定

可能在更新前指定日期为1/1/1900

update table set value = 1, date = getdate() 
where id = 1 and (date is null or date = '1/1/1900')

然后有一些机制将1/1/1900设置为定期为孤立