C#检测外键冲突的代码

简介:

大家都明白,在设计数据库的时候,外键的存在无可避免。在带来好处的同时(确保数据的完整性和一致性等,这些都不多说了),也有它的很多缺陷,那就是使诸如查询等相关操作的效率降低(但有的时候这也是没办法的事情,现在硬件发展都这么快了),但最主要的是,某些时候,在用户不知道各个实体关系的情况下,他们想去删某些记录,下面我们举个例子。

假设有一张产品类别表:Categary,一张产品表Product,其中产品表引用类表表中的类别编号作为外键。

如果出现这样一种情况,一个用户拥有这些表的删除权限,假设他拥有最高权限,也许此时考虑到数据一致性,你不会开放给用户Categary表记录的删除权限,但假设确实有这么种情况,这种产品类别的产品我们以后确实不会在这个系统中使用,也就是某种产品类别的存在没有意义。因此从可维护性的角度来讲,我们需要将这条记录删除是符合业务逻辑需要的。

但如果开放给用户权限吧,用户删除Categary中被Product表中记录引为外键的记录,会出现很多情况:代码不严谨,直接报错抛给用户,很悲剧;严谨点,捕获到异常,但只是告诉用户出错,这是通常的做法,但用户觉得很莫名其妙。如果Categary类别表中确实有垃圾记录,或者用户想删某条记录。我们需要在有外键约束冲突的情况下,给用户更友好的提示信息,或者提醒他,应该先删什么表中的什么数据,然后才能删这条记录等等。

下面是实现:

在项目数据库中增加一张表,该表有数据库管理员维护,此表是项目中其他表之间主外键关系的描述,我们不能直接告诉用户真实的主、外键表(出于安全),但我们可以告诉他们关于这些表功能的描述,让他们知道哪里有冲突,为什么不能删这条记录等等

表名:Sys_PrimaryForeignTables(系统主外键关系表)

字段名

类型

描述

id

Int PK not null

自增编号

primaryTables

Nvarchar(50) not null

主表(如部门表)

foreignTables

Nvarchar(50) not null

引入外键表(如学生表)

foreginId

Nvarchar(20) not null

外键表中的外键字段名

primaryRemark

Nvarchar(255) null

对主表的描述

foreignRemark

Nvarchar(255) null

对引入外键的表的描述

代码的实现:

namespace DTMS.DAL.Components.Common { /// <summary> /// 数据访问层——在删除之前检查是否存在外键约束(辅助类) /// </summary> public static class CheckFKReferences { /// <summary> /// 检查是否存在外键约束 /// </summary> /// <param name="id">要删除记录的主键</param> /// <param name="primaryTable">记录所在的表</param> public static string CheckFKBeforeDelete(string id, string primaryTable) { try { string errText = ""; //连接字符串 string connString = ConfigurationManager.ConnectionStrings["DTMS_DBConnectionString"].ConnectionString; DTMS.DTMS_LINQDataContext db = new DTMS_LINQDataContext(); //取得当前表的所有外键信息 var fts = db.Sys_PrimaryForeignTables.Where(pt => pt.primaryTables.Trim() == primaryTable).ToList(); string fId, fTable, strSQL; string[] sql, sqlArray; int count = 0; for (int i = 0; i < fts.Count; i++) { fId = fts[i].foreginId.Trim(); fTable = fts[i].foreignTables.Trim(); sql = new string[]{ "SELECT COUNT(*) FROM ", fTable, " WHERE ", fId, "='", id, "'" }; strSQL = string.Concat(sql); count = Convert.ToInt32(DTMS.DAL.DBUtility.SqlHelper.ExecuteScalar(connString, System.Data.CommandType.Text, strSQL_1)); if (count > 0) { sqlArray = new string[]{ "在删除[",fts[i].primaryRemark.Trim(),"]中的记录时,由于外键约束,所以该记录暂时无法删除。", "请确保将先[",fts[i].foreignRemark.Trim(),"]中关联的相关记录删除后,再执行此删除操作!"}; errText = string.Concat(sqlArray); LogTools.Instance.Log(errText); return errText; } } return ""; } catch (Exception ex) { throw ex; } } } }

实现很简单,相信你能看得懂,一般情况下,在DAL中,我们在对那些有键作为其他表的外键的表作删除的时候,会先去检查。当然,你也可以为此抽象出一个IDeleteable接口,让每个DAL中有删除操作的业务类去实现这个接口。




原文发布时间为:2010-06-15


本文作者:vinoYang


本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。

目录
相关文章
|
1月前
|
C# Windows
C#通过代码实现快捷键编辑
C#通过代码实现快捷键编辑
|
3月前
|
开发框架 .NET 编译器
C# 10.0中Lambda表达式的改进:更简洁、更灵活的代码编写体验
【1月更文挑战第21天】随着C#语言的不断发展,Lambda表达式作为一种简洁、高效的函数式编程工具,在C# 10.0中迎来了重要的改进。本文将详细探讨C# 10.0中Lambda表达式的新特性,包括参数类型的推断增强、自然类型的Lambda参数以及Lambda表达式的属性改进等。这些改进不仅简化了Lambda表达式的编写过程,还提升了代码的可读性和灵活性,为开发者带来了更优质的编程体验。
|
3月前
|
C# 开发者
C# 10.0中的文件范围命名空间:简化代码组织的新方式
【1月更文挑战第18天】C# 10.0引入了文件范围的命名空间,这是一种新的语法糖,用于更简洁地组织和管理代码。文件范围命名空间允许开发者在每个文件的基础上定义命名空间,而无需显式使用花括号包裹整个文件内容。本文将深入探讨文件范围命名空间的工作原理、使用场景以及它们为C#开发者带来的便利。
|
4月前
|
存储 人工智能 C#
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
36 0
|
5月前
|
开发框架 .NET C#
如何调试 C# Emit 生成的动态代码?
如何调试 C# Emit 生成的动态代码?
|
4月前
|
IDE C# 开发工具
C# | 多线程批量下载文件(创建N个线程同时批量下载文件,只需要几行代码而已)
批量下载文件时使用多线程可以有效缩短完成时间,本文将讲解如何使用C#+CodePlus扩展库快速完成多线程的文件下载。 大部分代码由IDE自动生成,需要我们自己编写的代码正好**10行**。也就是说,只需要10分钟,就可以手撸一个多线程的批量下载器。
85 0
C# | 多线程批量下载文件(创建N个线程同时批量下载文件,只需要几行代码而已)
|
2月前
|
数据采集 JSON 前端开发
从代码到内容:使用C#和Fizzler探索Instagram的深处
Instagram是一个流行的社交媒体平台,拥有数亿的用户和海量的图片和视频内容。如果您想要从Instagram上获取一些有用的信息或数据,您可能需要使用爬虫技术来自动化地抓取和分析网页内容。本文将介绍如何使用C#和Fizzler这两个强大的工具,来实现一个简单而高效的Instagram爬虫,从代码到内容,探索Instagram的深处。
|
3月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
30 0
|
3月前
|
存储 C# 容器
掌握 C# 变量:在代码中声明、初始化和使用不同类型的综合指南
变量是用于存储数据值的容器。 在 C# 中,有不同类型的变量(用不同的关键字定义),例如: int - 存储整数(没有小数点的整数),如 123 或 -123 double - 存储浮点数,有小数点,如 19.99 或 -19.99 char - 存储单个字符,如 'a' 或 'B'。Char 值用单引号括起来 string - 存储文本,如 "Hello World"。String 值用双引号括起来 bool - 存储具有两个状态的值:true 或 false
37 2
|
8月前
|
存储 C# 图形学
代码解析 C# 引用类型还是值类型
代码解析 C# 引用类型还是值类型