.Net中删除数据前进行外键冲突检测

在编写数据库系统中为了保证系统中数据的一致性最简便且安全的方法就是在DBMS中建立外键约束,但删除主键数据时如果违反了外键约束,尽管DBMS会给出错误提示,如SQL Server的提示信息“%1! 语句与 %2! %3! 约束 '%4!' 冲突。该冲突发生于数据库 '%6!',表 '%8!'%10!%11!%13!,但这些提示信息对最终用户来说,是不友好的,于是就自己写了个类,用来删除记录时的进行外键冲突检测,代码如下:

  1 None.gif using  System;
  2 None.gif using  System.Data;
  3 None.gif using  System.Data.SqlClient;
  4 None.gif using  Microsoft.ApplicationBlocks.Data;
  5 None.gif
  6 None.gif namespace  DataAccess.SQLServerDAL
  7 ExpandedBlockStart.gifContractedBlock.gif dot.gif
  8ExpandedSubBlockStart.gifContractedSubBlock.gif    /**////  
  9InBlock.gif    /// Check 的摘要说明。 
 10InBlock.gif    /// 
 11ExpandedSubBlockEnd.gif    ///  

 12InBlock.gif    public class Check 
 13ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif
 14ExpandedSubBlockStart.gifContractedSubBlock.gif        /**////   
 15InBlock.gif        /// DBMS中保存系统表的  
 16ExpandedSubBlockEnd.gif        ///   

 17InBlock.gif        const string DEFAULT_SYSTABLES = "systables";
 18ExpandedSubBlockStart.gifContractedSubBlock.gif        CkeckFKBeginDelete#region CkeckFKBeginDelete
 19ExpandedSubBlockStart.gifContractedSubBlock.gif        /**////   
 20InBlock.gif        /// 在删除记录之前先检测有无外键冲突  
 21InBlock.gif        ///
 22InBlock.gif        /// 事物对象  
 23InBlock.gif        /// 
 24InBlock.gif        /// 要执行删除操作的表名  
 25InBlock.gif        /// 
 26InBlock.gif        /// 要删除的记录的主键值  
 27InBlock.gif        /// 
 28InBlock.gif        /// 返回错误信息 
 29InBlock.gif        /// 
 30ExpandedSubBlockEnd.gif        /// true - 无冲突,false - 有冲突  

 31InBlock.gif        public bool CkeckFKBeginDelete(SqlTransaction trans, string tableName, string id, ref string errText)  
 32ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{   
 33InBlock.gif            string selectString; 
 34InBlock.gif            //SQL查询语句   
 35InBlock.gif            string fkTableName;  
 36InBlock.gif            //外键表名称   
 37InBlock.gif            string fkColumnName; 
 38InBlock.gif            //外键列名称   
 39InBlock.gif            object obj;    
 40InBlock.gif            //执行SQL查询返回值   
 41InBlock.gif            string description;  
 42InBlock.gif            //外键表含义
 43InBlock.gif            int count;    //外键表中引用了主键的记录数
 44ExpandedSubBlockStart.gifContractedSubBlock.gif            string[] tableNames = dot.gif{"sysforeignkeys"};
 45InBlock.gif            DataSet ds = BuildDataTables();
 46InBlock.gif            //检索所有此表的外键表   
 47InBlock.gif            selectString = "SELECT fkeyid, fkey FROM sysforeignkeys a, sysobjects b WHERE a.rkeyid = b.id AND b.name = @name";
 48InBlock.gif            SqlParameter name = new SqlParameter("@name", SqlDbType.VarChar);   name.Value = tableName;
 49InBlock.gif            SqlHelper.FillDataset(trans, CommandType.Text, selectString, ds, tableNames, name);
 50InBlock.gif            //外键表Id   
 51InBlock.gif            SqlParameter Id = new SqlParameter("@id", SqlDbType.Int);   //外键列Id   
 52InBlock.gif            SqlParameter colid = new SqlParameter("@colid", SqlDbType.Int);   //主键值   
 53InBlock.gif            SqlParameter keyid = new SqlParameter("@keyid", SqlDbType.Int);      //遍历所有的外键表   
 54InBlock.gif            foreach (DataRow dr in ds.Tables["sysforeignkeys"].Rows)   
 55ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{    //查询外键表名称    
 56InBlock.gif                selectString = "SELECT name FROM sysobjects WHERE id = @id";    
 57InBlock.gif                Id.Value = dr["fkeyid"];    
 58InBlock.gif                fkTableName = SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, Id).ToString();       
 59InBlock.gif                //查询外键列名称   
 60InBlock.gif                selectString = "SELECT name FROM syscolumns WHERE id = @id AND colid = @colid";    
 61InBlock.gif                Id.Value = dr["fkeyid"];    
 62InBlock.gif                colid.Value = dr["fkey"];    
 63InBlock.gif                fkColumnName = SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, Id, colid).ToString();
 64InBlock.gif                //查询外键表中有没有引用要删除的主键    selectString = "SELECT COUNT(*) FROM " + fkTableName + " WHERE " + fkColumnName + " = @keyid";    
 65InBlock.gif                keyid.Value = id;    
 66InBlock.gif                count = Convert.ToInt32(SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, keyid));
 67InBlock.gif    
 68InBlock.gif                if (count > 0)    
 69ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{    
 70InBlock.gif                    //查询发生冲突的表的含义,从而给用户发出友好的提示     
 71InBlock.gif                    selectString = "SELECT description FROM callCenterTables WHERE tableName = @tableName";     
 72InBlock.gif                    SqlParameter TableName = new SqlParameter("@tableName", SqlDbType.VarChar);     
 73InBlock.gif                    TableName.Value = fkTableName;
 74InBlock.gif                    obj = SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, TableName);
 75InBlock.gif                    if (obj != null)      
 76InBlock.gif                        description = obj.ToString();     
 77InBlock.gif                    else      
 78InBlock.gif                        description = fkTableName;
 79InBlock.gif                    errText = "您要删除的数据已在" + description + "中使用,要删除该条数据,请先删除" +      description + "中的相关数据,否则您将无法删除此条记录!";
 80ExpandedSubBlockEnd.gif                    return false;    }
   
 81ExpandedSubBlockEnd.gif            }

 82ExpandedSubBlockEnd.gif            return true;  }

 83ExpandedSubBlockEnd.gif        #endregion

 84ExpandedSubBlockStart.gifContractedSubBlock.gif        BuildDataTables#region BuildDataTables   
 85ExpandedSubBlockStart.gifContractedSubBlock.gif        /**////   
 86InBlock.gif        /// 创建外键DataTable  
 87InBlock.gif        /// 
 88ExpandedSubBlockEnd.gif        /// DataSet实例 

 89InBlock.gif        private DataSet BuildDataTables()  
 90ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 91InBlock.gif                DataSet ds = new DataSet();      
 92InBlock.gif            DataTable table;   
 93InBlock.gif            DataColumnCollection columns;
 94InBlock.gif            table   = new DataTable("sysforeignkeys");   
 95InBlock.gif            columns = table.Columns;
 96InBlock.gif            columns.Add("fkeyid"typeof(System.Int32));   
 97InBlock.gif            columns.Add("fkey"typeof(System.Int32));   
 98InBlock.gif            ds.Tables.Add(table);
 99ExpandedSubBlockEnd.gif            return ds;  }

100ExpandedSubBlockEnd.gif        #endregion
 
101ExpandedSubBlockEnd.gif    }

102ExpandedBlockEnd.gif}

103 None.gif
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

使用该类时需要在DBMS中建一张系统表,并维护表中的数据,该表用来记录系统中各用户表的大概含义,用来告诉用户是什么地方发生了冲突:

create table sysTables(id    int not null IDENTITY(1,1)
PRIMARY KEY CLUSTERED, /*ID*/
tableName  varchar(255),          /*
用户表名称*/
description  varchar(255)          /*
用户表描述*/)

调用示例:

None.gifpublic bool  test()  
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{   
InBlock.gif            
//数据库连接字符串   string connectionString = "";

InBlock.gif
            using (SqlConnection conn = new SqlConnection(connectionString))   
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif
{
InBlock.gif                conn.Open();    
InBlock.gif                
using (SqlTransaction trans =
 conn.BeginTransaction())     
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif
{
InBlock.gif                    
try
     
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif
{
InBlock.gif                        
string execSqlString = "DELETE FROM Test WHERE id = 1"
;      
InBlock.gif                        
string errText = ""
;
InBlock.gif                        
if (!new Check().CkeckFKBeginDelete(trans, "test"1ref
 errText))      
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif
{       
InBlock.gif                            trans.Rollback();       
InBlock.gif                            
return false
;      
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        SqlHelper.ExecuteNonQuery(trans, CommandType.Text, execSqlString);      
InBlock.gif                        trans.Commit();      
InBlock.gif                        
return true;     
ExpandedSubBlockEnd.gif                    }
     
InBlock.gif                    
catch
     
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif
{      
InBlock.gif                        trans.Rollback();      
InBlock.gif                        
throw
;     
ExpandedSubBlockEnd.gif                    }
    
ExpandedSubBlockEnd.gif                }
   
ExpandedSubBlockEnd.gif            }
  
ExpandedBlockEnd.gif        }

代码中用到msSqlHelper类,可以到http://msdn.microsoft.com/library/en-us/dnbda/html/daab-rm.asp下载。目前该类仅适用于SQL Server数据库

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值