如何从我的应用程序处理SQL键值表
本文关键字:SQL 键值 处理 应用程序 我的 | 更新日期: 2023-09-27 18:01:59
所以我有一个简单的键值表BillTypes在我的SQL Server。它看起来像这样:
+----+-------------+
| Id | Description |
+----+-------------+
| 1 | OK |
| 2 | Missing |
| 3 | Maximum |
| 4 | Minimum |
| 5 | Error |
+----+-------------+
表保存不同类型的账单状态。我有另一个表Items,外键BillType,引用上一个表中的Id。
+----------+------+--------+
| IdItem | Cash |BillType|
+----------+------+--------+
| * | * | * |
| * | * | * |
| * | * | * |
| ... |... | ... |
+----------+------+--------+
然后,在我的应用程序中,我通过存储过程从第二个表中获取数据。在这个sp中,我不确定是应该选择BillType,还是tinyint,还是使用innerjoin来返回描述。问题是,我的应用程序有一些依赖于BillType的逻辑,即行将根据BillType进行不同的处理。我的逻辑应该依赖于Id还是描述?
在代码中,我应该有这样的东西吗?DataTable dt = ...//call stored procedure that selects the BillType id
foreach(Datarow r in dt)
{
if(r["BillType"] == 3) ... //use logic
}
还是这个?
DataTable dt = ...//call stored procedure that selects the BillType description
foreach(Datarow r in dt)
{
if(r["BillType"] == "Maximum") ... //use logic
}
我目前使用第二种方式,带描述,因为我认为它使代码更具可读性。然而,我担心有人可能会更改描述并破坏我的应用程序逻辑。另一方面,使用id会降低可读性(尽管我可以使用enum来解决这个问题),并且不会受到描述更改的影响,但是如果有人更改了id,事情就会中断。
老实说,我们不希望任何人乱动第一个表,因为我们专门为这个应用程序制作了它。不过,我是SQL新手,我正在努力学习应用程序-SQL交互的最佳实践,所以我想知道有经验的人是如何做的
请将此视为评论而不是回答(我还没有足够的代表来评论)
我更喜欢后者(正如你所做的),我依赖于描述。
如果您的id是SQL标识字段(会自动增加),请考虑以下场景:
- 在DEV环境中构建应用程序和数据库
- 生产部署退出并重新运行
- 现在,id号不是1,2,3而是4,5,6
一般来说,依赖id比依赖值更有意义。毕竟,id应该是唯一的,而值可以有重复/更改。虽然您不希望对BillTypes表进行任何更改,但我不会像您建议的那样使用字符串值。
由于更新/删除/插入仍然可以在BillTypes表中发生,并且您希望准备好并具有可读的代码,因此最简单的方法是定义自己的enum:
public Enum BillTypesEnum
{
OK = 1,
Missing = 2,
Maximum = 3,
Minimum = 4,
Error = 5
};
如果发生了什么事情,你需要添加一些东西到数据库,你这样做,然后改变Enum。如果删除"Error"条目并插入"Average"条目,它也可以工作。你不会得到平均值=5,但可能会得到平均值=6或更高的值。枚举结构使您可以毫无问题地定义值。
那么你就可以在整个代码中使用它,而不仅仅是在这个实例中。您的代码修改如下:
DataTable dt = ...//call stored procedure that selects the BillType id
foreach(Datarow r in dt)
{
if(r["BillType"] == (int)BillTypesEnum.Maximum) ... //use logic
}
这使得代码比以前更具可读性,你不必在你的代码中硬编码所有的值,但只在一个地方。如果它发生了,你不会改变数据库,那么它就是一个加号。
另一个选项是执行spGetAllBillTypes (select * from tblBillTypes),然后在内部创建一个字典。
Dictionary<string,int> dictBillTypes = new Dictionary<string,int>();
int = billTypeIdstring = billTypeText
当您从子表(带有外键的表)检索数据时,您将检索您的billtypetext。
你可以这样做:
DataTable dt = ...//call stored procedure that selects the BillType id
foreach(Datarow r in dt)
{
if(r["BillType"] == dictBillTypes["Maximum"]) ... //use logic
}
…但这仍然是一个不完整的解决方案,因为在这里,你依赖于两件事:1. billTypeText不会更改(如果更改了,则必须在代码中更改)2. billTypeText不能有重复项(否则你会得到一个关于字典中重复键值的异常)
另一个选项是把它转过来:
Dictionary<int,string> dict = new Dictionary<int,string>();
并根据值而不是键进行搜索。但这会使代码可读性降低,而且你并没有从中获得很多好处。
如果您担心ID更改,我建议创建一个Abstract Class
来保存ID值。可以像引用Enum
一样引用它,它将在第一次调用时查找ID,并缓存结果:
public abstract class BillType
{
private static readonly string c_ok = "ok";
private static readonly string c_missing = "missing";
private static readonly string c_maximum = "maximum";
private static readonly string c_minimum = "minumum";
private static readonly string c_error = "error";
private static int? _ok = null;
private static int? _missing = null;
private static int? _maximum = null;
private static int? _minimum = null;
private static int? _error = null;
public static int OK
{
get
{
if (_ok == null)
_ok = GetBillTypeID(c_ok);
return (int)_ok;
}
}
public static int Missing
{
get
{
if (_missing == null)
_missing = GetBillTypeID(c_missing);
return (int)_missing;
}
}
public static int Maximum
{
get
{
if (_maximum == null)
_maximum = GetBillTypeID(c_maximum);
return (int)_maximum;
}
}
public static int Minimum
{
get
{
if (_minimum == null)
_minimum = GetBillTypeID(c_minimum);
return (int)_minimum;
}
}
public static int Error
{
get
{
if (_error == null)
_error = GetBillTypeID(c_error);
return (int)_error;
}
}
private static int GetBillTypeID(string identifier)
{
using (SqlConnection conn = new SqlConnection("your connection string")
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("spGetBillTypeId", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("Description", identifier);
return Convert.ToInt32(cmd.ExecuteScalar());
}
}
}
}
我也会有一个Stored Procedure
在你的数据库做查找ID:
Create Procedure spGetBillTypeId (@Description Varchar (20))
As Begin
Select Id
From BillTypes
Where Description = @Description
End
有了这个,您可以简单地调用BillType.Missing
,它将提取缺失的Id,缓存它,并返回2
。
(注意,这大部分是复制/粘贴,所以注意随机错误,我没有捕捉到)。
如果您不希望值改变,但是,如果发生这种情况,您可以修改代码,您可以简单地创建一个Enum
:
public enum BillType
{
OK = 1,
Missing = 2,
Maximum = 3,
Minimum = 4,
Error = 5
}