C# 如何使用数据库C中的值创建枚举#
我在数据库中有一个状态表,我在整个应用程序中使用它的值。状态表将具有(ID、名称)。我想创建一个StatusEnum,我可以在应用程序的代码中使用它。如何使用数据库中的值创建枚举 目前我有这样的枚举C# 如何使用数据库C中的值创建枚举#,c#,enums,C#,Enums,我在数据库中有一个状态表,我在整个应用程序中使用它的值。状态表将具有(ID、名称)。我想创建一个StatusEnum,我可以在应用程序的代码中使用它。如何使用数据库中的值创建枚举 目前我有这样的枚举 enum StatusCode: int { Open = 20, Received = 21, Delivered= 22, Cancelled = 23 } 但我想从数据库中设置值。您真的不能这样做。您将需要一些帮助函数来帮助您 enum StatusCode
enum StatusCode: int
{
Open = 20,
Received = 21,
Delivered= 22,
Cancelled = 23
}
但我想从数据库中设置值。您真的不能这样做。您将需要一些帮助函数来帮助您
enum StatusCode
{
Open,
Received,
Delivered,
Cancelled
}
private Dictionary<StatusCode, int> storedCodes = new Dictionary<StatusCode, int>();
public static int GetValue(StatusCode code)
{
//Return code from database
return storedCodes[code];
}
public static void SetValue(StatusCode code, int value)
{
storedCodes[code] = value;
//Set values from database
//Note: you can't set the value of your enums here
//Just a place to set some other variables to remember what the values are.
}
enum StatusCode
{
打开
收到,
交付,
取消
}
私有字典storedCodes=新字典();
公共静态int GetValue(状态代码)
{
//从数据库返回代码
返回存储的代码[代码];
}
公共静态无效设置值(状态代码、int值)
{
storedCodes[code]=值;
//从数据库中设置值
//注意:您不能在此处设置枚举的值
//只是一个设置其他变量以记住值的地方。
}
你真的不能这么做。您将需要一些帮助函数来帮助您
enum StatusCode
{
Open,
Received,
Delivered,
Cancelled
}
private Dictionary<StatusCode, int> storedCodes = new Dictionary<StatusCode, int>();
public static int GetValue(StatusCode code)
{
//Return code from database
return storedCodes[code];
}
public static void SetValue(StatusCode code, int value)
{
storedCodes[code] = value;
//Set values from database
//Note: you can't set the value of your enums here
//Just a place to set some other variables to remember what the values are.
}
enum StatusCode
{
打开
收到,
交付,
取消
}
私有字典storedCodes=新字典();
公共静态int GetValue(状态代码)
{
//从数据库返回代码
返回存储的代码[代码];
}
公共静态无效设置值(状态代码、int值)
{
storedCodes[code]=值;
//从数据库中设置值
//注意:您不能在此处设置枚举的值
//只是一个设置其他变量以记住值的地方。
}
您可以
- 手动使枚举定义与数据库保持同步。这是最简单的方法
- 您可以为VisualStudio(也称为a)使用,并让它从某个参考数据库生成枚举定义。单文件生成器获取一些源文件(例如,*.aspx)并从中生成代码(例如.*.designer.cs)。能够做到这一点非常有用
- 第三种技术是前两种技术的雌雄同体变体:编写一个独立的工具从数据库生成枚举定义。对引用数据库运行该工具以重新生成文件并将其检入
- 手动使枚举定义与数据库保持同步。这是最简单的方法
- 您可以为VisualStudio(也称为a)使用,并让它从某个参考数据库生成枚举定义。单文件生成器获取一些源文件(例如,*.aspx)并从中生成代码(例如.*.designer.cs)。能够做到这一点非常有用
- 第三种技术是前两种技术的雌雄同体变体:编写一个独立的工具从数据库生成枚举定义。对引用数据库运行该工具以重新生成文件并将其检入
但据推测,您需要枚举的类型都是相对稳定的类型。我将尝试一个答案 如果您的想法是在数据库中有神奇的数字,它们本质上是
const
,这意味着它们很少改变,那么我可以理解为什么您希望将它们表示为代码中可读的东西
根据查询数据的方式,有不同的方法将此数据表示为枚举值:
对于SqlDataReader
只需将来自记录的整数值向上投射到枚举:
int statusCodeValue = row["status"];
// But BEWARE as undefined values also upcast to the enum just fine
// but just won't have any of the defined values
if (!Enum.IsDefined(typeof(StatusCode), statusCodeValue)) throw new Exception();
StatusCode statusCode = (StatusCode)statusCodeValue;
如果您使用的是像nHibernate或EF这样的ORM,那么就可以直接使用这种映射。只需在数据模型上定义enum属性,它就会正确映射
笔记
您需要考虑谁是数据的所有者。这些数据是来自另一个系统,还是您的应用程序生成的
如果是外来的,则需要手动保持数据和应用程序枚举同步。
如果它是本地的,请确保为每个枚举成员分配一个整数值,并且永远不要更改该整数值在语义上应该表示的值。我将尝试一个答案 如果您的想法是在数据库中有神奇的数字,它们本质上是
const
,这意味着它们很少改变,那么我可以理解为什么您希望将它们表示为代码中可读的东西
根据查询数据的方式,有不同的方法将此数据表示为枚举值:
对于SqlDataReader
只需将来自记录的整数值向上投射到枚举:
int statusCodeValue = row["status"];
// But BEWARE as undefined values also upcast to the enum just fine
// but just won't have any of the defined values
if (!Enum.IsDefined(typeof(StatusCode), statusCodeValue)) throw new Exception();
StatusCode statusCode = (StatusCode)statusCodeValue;
如果您使用的是像nHibernate或EF这样的ORM,那么就可以直接使用这种映射。只需在数据模型上定义enum属性,它就会正确映射
笔记
您需要考虑谁是数据的所有者。这些数据是来自另一个系统,还是您的应用程序生成的
如果是外来的,则需要手动保持数据和应用程序枚举同步。
如果它是本地的,只需确保为每个枚举成员分配一个整数值,并且永远不要更改该整数值在语义上应该表示的值。通过文本模板,您所要求的在技术上是可能的(折叠后就是一个示例)。然而,正如已经指出的,好的文本模板并不容易,通常需要与应用程序代码一样多的维护 相反,请查看并确定您的枚举是否真的是所有可能的
/* SQL */
SELECT * FROM entity WHERE status = 20;
/* C# */
if (entity.Status == StatusCodes.Open) { /* do something */ }
if (entity.Status == 20) { /* do something */ }
/* SQL */
SELECT * FROM entity WHERE is_closed = 0;
/* C# */
if (!entity.IsClosed) { /* do something */ }
// (untested, pseudo-ish code -- WATCH FOR INJECTION!)
StringBuilder sql = new StringBuilder();
sql.Append(@"ALTER TABLE [my_table] ADD CONSTRAINT chk_status_code CHECK (status_code IN (");
bool first = true;
foreach (var v in Enum.GetValues(typeof(StatusCode)) {
if (!first) sql.Append(", ");
sql.Append(v);
first = false;
}
sql.Append("));");
// write sql to file, or run against the development database
// (untested, pseudo-ish code -- WATCH FOR INJECTION!)
StringBuilder sql = new StringBuilder();
sql.AppendLine(@"IF OBJECT_ID('dbo.tf_status_codes') IS NULL EXECUTE('
CREATE FUNCTION dbo.tf_status_codes RETURNS TABLE AS RETURN (
SELECT ''not yet built'' AS err
)
')");
sql.AppendLine(@"ALTER FUNCTION dbo.tf_status_codes RETURNS TABLE AS RETURN (")
.AppendLine(@" SELECT value, name FROM (VALUES ")
bool first = true;
foreach (var v in Enum.GetValues(typeof(StatusCode)) {
if (!first) sql.AppendLine(",");
sql.Append(@" ({0}, '{1}')",
v,
Enum.GetName(typeof(StatusCode), v));
first = false;
}
sql.AppendLine(@" ) e(value, name);")
.AppendLine(@")";
// write sql to file, or run against the development database
CREATE FUNCTION dbo.status_codes
RETURNS TABLE
AS RETURN (
SELECT value, name
FROM (VALUES (20, 'Open')
,(21, 'Received')
,(22, 'Delivered')
,(23, 'Cancelled')) AS v(value, name)
)
// untested, pseudo, assumes an existing database connection routine
IDataReader reader = DB.GetReader("SELECT value, name FROM dbo.status_codes()");
StringBuilder code = new StringBuilder();
code.AppendLine("namespace MyApp {")
.AppendLine(" public enum StatusCodes : int {");
bool first = true
while (reader.Read()) {
if (!first) code.AppendLine(",");
code.Append(" {0} = {1}", reader["name"], reader["value"]);
first = false;
}
code.AppendLine(" }")
.AppendLine("}");
// ...write the code to the Enum class file, and exit with 0 code