ObjectDataSourc用法之八(并发控制)

在进行数据库的操作中,更新和删除操作可能会引起冲突:
假设有A,B两个人同时取到如下表中的一行元组值:
 id    书名(varchar(max))        是否过期(bit)
 7   《c#开发》                       1
可以看到当AB两人取到的这个记录是id:7,书名:《c#开发》,是否过期:1(1表示过期了,0表示没过期)
现在A觉得这本书过期了要将这条记录删除掉,B因为发现这本书应该是没有过期的想立即将其是否过期设置为0
由于B手脚快些所以先执行了update,现在数据库中这条记录应该是:
 id    书名(varchar(max))        是否过期(bit)
 7   《c#开发》                       0
但是A看到的还是
 id    书名(varchar(max))        是否过期(bit)
 7   《c#开发》                       1
所以A就执行了delete命令将这条记录删除了
那么事实上A就将一本不该删除的书删除了
犯下这种错误既不能怪A,也不能怪B,是因为A看到的并不是最新的信息,设想如果在A进行delete操作之前,将这条记录从数据库检索出来,在和A刚开始看到这条记录时候的值进行对比,如果值发生了变化有取消删除操作,没有改变再进行执行delete,就不会发生这种悲剧

这就要求对程序进行并发控制,而ObjectDataSource为我们提供了并发控制机制:

ObjectDataSource 控件有一个属性ConflictDetection , 叫做冲突检测.  可以设置再应用程序中如何处理并发冲突.
ConflictDetection 有两个可选值:

默认设置为OverwriteChanges 这是最小化的并发冲突设置,在更新和删除的时候不会提供原始数据信息,无法进行并发控制.  
CompareAllValues 这将给予你最大的灵活性,它将在更新和删除的时候提供原始的数据信息,所以可以进行并发控制
请看如下示例:
用于ObjectDataSource的实体对象类:

public   class  Student
{
    
private   int  _id;
    
public   string  _name;
    
private   int  _age;
    
private   bool  _sex;

    
public   int  Id
    {
        
set
        {
            _id 
=  value;
        }
        
get
        {
            
return  _id;
        }
    }

    
public   string  Name
    {
        
set
        {
            _name 
=  value;
        }
        
get
        {
            
return  _name;
        }
    }

    
public   int  Age
    {
        
set
        {
            _age 
=  value;
        }
        
get
        {
            
return  _age;
        }
    }

    
public   bool  Sex
    {
        
set
        {
            _sex 
=  value;
        }
        
get
        {
            
return  _sex;
        }
    }

    
public  Student()
    {

    }
}


ObjectDataSource和GridView的设置:

< asp:GridView  ID ="GridView1"  runat ="server"  AutoGenerateColumns ="False"  DataSourceID ="ObjectDataSource1"  AllowPaging ="True"  PageSize ="5"  AllowSorting ="True"  DataKeyNames ="Id" >
            
< Columns >
                
< asp:CommandField  ShowDeleteButton ="True"  ShowEditButton ="True"   />
                
< asp:BoundField  DataField ="Id"  HeaderText ="Id"  SortExpression ="Id"   />
                
< asp:BoundField  DataField ="Name"  HeaderText ="Name"  SortExpression ="Name"   />
                
< asp:BoundField  DataField ="Age"  HeaderText ="Age"  SortExpression ="Age"  ReadOnly ="true"   />
                
< asp:CheckBoxField  DataField ="Sex"  HeaderText ="Sex"  SortExpression ="Sex"   />
            
</ Columns >
        
</ asp:GridView >
        
< asp:ObjectDataSource  ID ="ObjectDataSource1"  runat ="server"  DeleteMethod ="DeleteStudent"
            SelectMethod
="GetPageStudent"  TypeName ="StudentDAL"  UpdateMethod ="UpdateStudent"  OldValuesParameterFormatString ="old_{0}"  EnablePaging ="True"  MaximumRowsParameterName ="size"  SelectCountMethod ="GetAllCount"  StartRowIndexParameterName ="start"  SortParameterName ="order"  InsertMethod ="InsertStudent"  DataObjectTypeName ="Student"   >
            
< InsertParameters >
                
< asp:Parameter  Name ="Name"  Type ="String"   />
                
< asp:Parameter  Name ="Age"  Type ="Int32"   />
                
< asp:Parameter  Name ="Sex"  Type ="Boolean"   />
            
</ InsertParameters >
            
< UpdateParameters >
                
< asp:Parameter  Name ="s"  Type ="Object"   />
                
< asp:Parameter  Name ="old_s"  Type ="Object"   />
            
</ UpdateParameters >
        
</ asp:ObjectDataSource >
        
< asp:Button  ID ="btnAdd"  runat ="server"  OnClick ="btnAdd_Click"  Text ="Add"   />


然后是最关键的!后台供ObjectDataSource调用的DAL层次代码:

using  System;
using  System.Data;
using  System.Data.SqlClient;
using  System.Configuration;
using  System.Collections.Generic;
using  System.Web;
using  System.Web.Security;
using  System.Web.UI;
using  System.Web.UI.WebControls;
using  System.Web.UI.WebControls.WebParts;
using  System.Web.UI.HtmlControls;

///   <summary>
///  StudentDAL 的摘要说明
///   </summary>
public   class  StudentDAL
{
    
string  conn  =   " Data Source=localhost;Initial Catalog=qy;Integrated Security=True " ;
    SqlConnection oConn;
    SqlCommand oCommand;

    
public  StudentDAL()
    {
        oConn 
=   new  SqlConnection(conn);
        oCommand 
=   new  SqlCommand();
    }

    
public   int  GetAllCount()
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " select count(*) as T from Test_Student " ;
        
int  count = Convert.ToInt32(oCommand.ExecuteScalar());
        oConn.Close();

        
return   50 ;
    }


    
public  List < Student >  GetPageStudent( int  start, int  size, string  order)
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " select * from Test_Student " ;
        DataTable dt 
=   new  DataTable();
        SqlDataAdapter sda 
=   new  SqlDataAdapter(oCommand);
        sda.Fill(dt);
        oConn.Close();

        List
< Student >  students  =   new  List < Student > ();
        
int  i;
        
for  (i  =   0 ; i  <  dt.Rows.Count; i ++ )
        {
            Student s 
=   new  Student();
            s.Id 
=  Convert.ToInt32(dt.Rows[i][ " ID " ]);
            s.Name 
=  dt.Rows[i][ " Name " ].ToString();
            s.Age 
=  Convert.ToInt32(dt.Rows[i][ " Age " ]);
            s.Sex 
=  Convert.ToBoolean(dt.Rows[i][ " Sex " ]);
            students.Add(s);
        }

        
return  students;
    }

    
public   void  InsertStudent(Student s)
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        
string  sql  =   " insert into Test_Student(Name,Age,Sex) values(' "   +  s.Name  +   " ', "   +  s.Age.ToString()  +   " , "   +  Convert.ToInt32(s.Sex)  +   " ) " ;
        oCommand.CommandText 
=  sql;
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }

    
public   void  InsertStudent( string  Name, int  Age, bool  Sex)
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        
string  sql  =   " insert into Test_Student(Name,Age,Sex) values(' "   +  Name  +   " ', "   +  Age.ToString()  +   " , "   +  Convert.ToInt32(Sex)  +   " ) " ;
        oCommand.CommandText 
=  sql;
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }


    
public   void  UpdateStudent(Student s) // 在DataObjectType模式下,ConflictDetection= Overwrite Changes的时候,只需要传入一个Student,来进行更新
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        
string  sql  =   " update Test_Student set Name=' "   +  s.Name  +   " ',Age= "   +  s.Age.ToString()  +   " ,Sex= "   +  Convert.ToInt32(s.Sex)  +   "  where id= "   +  s.Id.ToString();
        oCommand.CommandText 
=  sql;
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }


    
public   void  UpdateStudent(Student s, Student old_s) // 在DataObjectType模式下,ConflictDetection=CompareAllValues需要两个Student,一个叫s里边记录了更新的字段信息,另外个叫old_s(这个对象名是根据ObjectDataSource的OldValuesParameterFormatString设置的格式old_{0})记录了原始的字段信息,然后比较两个Student对象进行冲突检测
    {
        //冲突检测逻辑.....略
        int  Age  =   0 ;
        oConn.Open();
        oCommand.Connection 
=  oConn;
        
string  sql  =   " update Test_Student set Name=' "   +  s.Name  +   " ',Age= "   +  Age.ToString()  +   " ,Sex= "   +  Convert.ToInt32(s.Sex)  +   "  where id= "   +  s.Id.ToString();
        oCommand.CommandText 
=  sql;
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }

    
public   void  UpdateStudent( int  old_Id,  string  Name,  bool  Sex,  int  Id,  int  Age) // ObjectDataSource在ConflictDetection= Overwrite Changes的时候要求只把现在更新的字段,以及原来的主键字段old_{DataKeyName}(这个名字是根据ObjectDataSource的OldValuesParameterFormatString设置的格式old_{0})传进来,以便索引到更新行
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " update Test_Student set Name=' "   +  Name  +   " ',Age= "   +  Age.ToString()  +   " ,Sex= "   +  Convert.ToInt32(Sex).ToString()  +   "  where id= "   +  old_Id.ToString();
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }

    
public   void  UpdateStudent( int  old_Id,  string  Name,  bool  Sex,  int  Id,  int  Age,  string  old_Name,  bool  old_Sex,  int  old_Age) // ObjectDataSource在ConflictDetection= CompareAllValues的时候要求把现在更新的字段,以及原来的字段old_{0}(这个名字是根据ObjectDataSource的OldValuesParameterFormatString设置的格式old_{0})都传进来,以便进行冲突检测,然后再更新
    {
        //冲突检测逻辑.....略
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " update Test_Student set Name=' "   +  Name  +   " ',Age= "   +  Age.ToString()  +   " ,Sex= "   +  Convert.ToInt32(Sex).ToString()  +   "  where id= "   +  old_Id.ToString();
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }

    
public   void  DeleteStudent(Student s) // 在DataObjectType模式下,ConflictDetection= Overwrite Changes/CompareAllValues只需要一个Student就可以了,因为传过来的记录本来就含有删除字段的所有属性,可以进行冲突检测
    {
        //冲突检测逻辑.....略
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " delete from Test_Student where id= "   +  s.Id.ToString();
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }

    
public   void  DeleteStudent( int  old_Id) // ObjectDataSource在ConflictDetection= Overwrite Changes的时候只会把old_{DataKeyName}的字段传进来,所以GridView如果没有设置DataKeyName,那么参数就不会传进来,也无法执行删除的sql语句
    {
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " delete from Test_Student where id= "   +  old_Id.ToString();
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }

    
public   void  DeleteStudent( int  old_Id,  string  old_Name,  bool  old_Sex,  int  old_Age) // ObjectDataSource在ConflictDetection= CompareAllValues的时候要求把现在更新的字段,以及原来的字段old_{0}都传进来,以便进行冲突检测
    {
        //冲突检测逻辑.....略
        oConn.Open();
        oCommand.Connection 
=  oConn;
        oCommand.CommandText 
=   " delete from Test_Student where id= "   +  old_Id.ToString();
        oCommand.ExecuteReader(CommandBehavior.CloseConnection);
    }
}

 

转载于:https://www.cnblogs.com/OpenCoder/archive/2009/09/17/1568747.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值