using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.ApplicationBlocks.Data;
namespace DataAccess.SQLServerDAL
{
///
/// Check 的摘要說明。
///
public class Check
{
///
/// DBMS中保存系統表的
///
const string DEFAULT_SYSTABLES = "systables";
#region CkeckFKBeginDelete
///
/// 在刪除記錄之前先檢測有無外鍵衝突
///
/// 事物對象
/// 要執行刪除操作的表名
/// 要刪除的記錄的主鍵值
/// 返回錯誤信息
/// true - 無衝突,false - 有衝突
public bool CkeckFKBeginDelete(SqlTransaction trans, string tableName, string id, ref string errText)
{
string selectString; //SQL查詢語句
string fkTableName; //外鍵表名稱
string fkColumnName; //外鍵列名稱
object obj; //執行SQL查詢返回值
string description; //外鍵表含義
int count; //外鍵表中引用了主鍵的記錄數
string[] tableNames = {"sysforeignkeys"};
DataSet ds = BuildDataTables();
//檢索所有此表的外鍵表
selectString = "SELECT fkeyid, fkey FROM sysforeignkeys a, sysobjects b WHERE a.rkeyid = b.id AND b.name = @name";
SqlParameter name = new SqlParameter("@name", SqlDbType.VarChar);
name.Value = tableName;
SqlHelper.FillDataset(trans, CommandType.Text, selectString, ds, tableNames, name);
//外鍵表Id
SqlParameter Id = new SqlParameter("@id", SqlDbType.Int);
//外鍵列Id
SqlParameter colid = new SqlParameter("@colid", SqlDbType.Int);
//主鍵值
SqlParameter keyid = new SqlParameter("@keyid", SqlDbType.Int);
//遍歷所有的外鍵表
foreach (DataRow dr in ds.Tables["sysforeignkeys"].Rows)
{
//查詢外鍵表名稱
selectString = "SELECT name FROM sysobjects WHERE id = @id";
Id.Value = dr["fkeyid"];
fkTableName = SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, Id).ToString();
//查詢外鍵列名稱
selectString = "SELECT name FROM syscolumns WHERE id = @id AND colid = @colid";
Id.Value = dr["fkeyid"];
colid.Value = dr["fkey"];
fkColumnName = SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, Id, colid).ToString();
//查詢外鍵表中有沒有引用要刪除的主鍵
selectString = "SELECT COUNT(*) FROM " + fkTableName + " WHERE " + fkColumnName + " = @keyid";
keyid.Value = id;
count = Convert.ToInt32(SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, keyid));
if (count > 0)
{
//查詢發生衝突的表的含義,從而給用戶發出友好的提示
selectString = "SELECT description FROM callCenterTables WHERE tableName = @tableName";
SqlParameter TableName = new SqlParameter("@tableName", SqlDbType.VarChar);
TableName.Value = fkTableName;
obj = SqlHelper.ExecuteScalar(trans, CommandType.Text, selectString, TableName);
if (obj != null)
description = obj.ToString();
else
description = fkTableName;
errText = "您要刪除的數據已在" + description + "中使用,要刪除該條數據,請先刪除" +
description + "中的相關數據,否則您將無法刪除此條記錄!";
return false;
}
}
return true;
}
#endregion
#region BuildDataTables
///
/// 創建外鍵DataTable
///
/// DataSet實例
private DataSet BuildDataTables()
{
DataSet ds = new DataSet();
DataTable table;
DataColumnCollection columns;
table = new DataTable("sysforeignkeys");
columns = table.Columns;
columns.Add("fkeyid", typeof(System.Int32));
columns.Add("fkey", typeof(System.Int32));
ds.Tables.Add(table);
return ds;
}
#endregion
}
}
使用該類時需要在DBMS中建一張系統表,並維護表中的數據,該表用來記錄系統中各用戶表的大概含義,用來告訴用戶是什麼地方發生了衝突:
create table sysTables
(
id int not null IDENTITY(1,1) PRIMARY KEY CLUSTERED, /*ID*/
tableName varchar(255), /*用戶表名稱*/
description varchar(255) /*用戶表描述*/
)
調用示例:
public bool test()
{
//數據庫連接字符串
string connectionString = "";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction())
{
try
{
string execSqlString = "DELETE FROM Test WHERE id = 1";
string errText = "";
if (!new Check().CkeckFKBeginDelete(trans, "test", 1, ref errText))
{
trans.Rollback();
return false;
}
SqlHelper.ExecuteNonQuery(trans, CommandType.Text, execSqlString);
trans.Commit();
return true;
}
catch
{
trans.Rollback();
throw;
}
}
}
}
代碼中用到ms的SqlHelper類,可以到http://msdn.microsoft.com/library/en-us/dnbda/html/daab-rm.asp下載。目前該類僅適用於SQL Server數據庫