C# 如何使用数据库C中的值创建枚举#

C# 如何使用数据库C中的值创建枚举#,c#,enums,C#,Enums,我在数据库中有一个状态表,我在整个应用程序中使用它的值。状态表将具有(ID、名称)。我想创建一个StatusEnum,我可以在应用程序的代码中使用它。如何使用数据库中的值创建枚举 目前我有这样的枚举 enum StatusCode: int { Open = 20, Received = 21, Delivered= 22, Cancelled = 23 } 但我想从数据库中设置值。您真的不能这样做。您将需要一些帮助函数来帮助您 enum StatusCode

我在数据库中有一个状态表,我在整个应用程序中使用它的值。状态表将具有(ID、名称)。我想创建一个StatusEnum,我可以在应用程序的代码中使用它。如何使用数据库中的值创建枚举

目前我有这样的枚举

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