使用FlagsAttribute将Enum解析为SqlParameter

时间:2011-05-22 05:16:29

标签: c# sql sql-server stored-procedures enums

我有一个Enum with Flags属性。

  [Flags]
    public enum AlcoholStatus
    {
        NotRecorded = 1,
        Drinker = 2,
        NonDrinker = 4
    }

我正在创建一个Sql参数,如下所示。

new SqlParameter("@AlcoholStatus", SqlDbType.VarChar) {Value = (int) AlcoholStatus}

如果AlcoholStatus具有所有值(NotRecorded | Drinker | NonDrinker),则返回7作为SqlParameter的值。

我正在为存储过程解析此参数,如果我可以将值解析为“1,2,3”,我更喜欢。这样做的最佳方式是什么?

或者还有其他简单的方法可以通过将整数值7解析为存储过程来过滤记录吗?

编辑:这发生在功能上的过滤器中,用户希望看到具有上述任何状态的人。 这是一个非常复杂的SQL查询。在那里我过滤AlcoholStatus如下

WHERE AlcoholStatus IN "1,2,4,"

5 个答案:

答案 0 :(得分:8)

不考虑枚举是否有意义作为[Flags],IMO是存储此数据的唯一合理方法是int列。只需存储值 - 不需要任何其他内容。试图将其强制为varchar是一个错误。数据库的工作是存储数据,而不是关心演示。

如果需要按此过滤,则可以在搜索中使用按位运算符,但请注意,由于在组合搜索时(而不是通过相等,可以使用非聚集索引),性能会受到影响。如果您需要在任意组合上搜索,请考虑使用非规范化。如果您只需要在可预测的位上搜索,那么您可以使用计算的持久索引列提取它们 - 即您可以使用代表的自动IsDrinker列(bit)第2位。

答案 1 :(得分:2)

如果你在WHERE子句中启动AND值,你可以将7传递给存储过程,并告别与AlcoholStatus列上的索引可能获得的任何好处。

如果你需要建立一串ID,那么下面的内容可能就是你所追求的。根据需要进行优化 - 例如,我没有考虑到枚举中只有三个标记。

如果您在构建语句时在SQL中摆弄字符串,那么您还需要注意SQL注入。

string values = "";
for(int i = 0; i < 30; ++i) {
  if((((int)AlcoholStatus) & (1 << i)) != 0) {
    if(values != "") {
      values += ",";
    }

    values += (i + 1).ToString();
  }
}

答案 2 :(得分:1)

在前面,我对续集服务器知之甚少......但是......

您的意思是假想的“客户”类的new SqlParameter("@AlcoholStatus", SqlDbType.VarChar) {Value = (int) client.AlcoholStatus}(而不是枚举类型 AlcoholStatus)?

此外,我倾向于认为“二进制标志”字段将“自然地”存储在整数字段中......并且可能是未签名的字段。 VarChar似乎是一个奇怪的选择。

答案 3 :(得分:0)

如果我理解正确,您正在尝试过滤某些情况,例如,您可以对您的位置使用按位运算,例如SELECT * FROM MyTable WHERE AlcoholStatus&amp; 0x3会同时选择Not Recorded和Drinker。您还可以将一个存储过程放在一起,通过使用一系列CASE WHEN将AlcoholStatus转换为1,2,3之类的字符串。

答案 4 :(得分:0)

我写下面的方法来获取逗号分隔的枚举ID,以便将其解析为数据库。

private static string GetAlcoholStatuses(Enums.Enums.AlcoholStatus? alcoholStatus)
{
    if (alcoholStatus == null)
        return string.Empty;

    Enums.Enums.AlcoholStatus alcoholStatusValue = alcoholStatus.Value;
    string alcoholStatuses = string.Empty;

    if (alcoholStatusValue.HasFlag(Enums.Enums.AlcoholStatus.Drinker))
    {
        alcoholStatuses = string.Format("{0}{1}{2}", alcoholStatuses, (int)Enums.Enums.AlcoholStatus.Drinker, ",");
    }
    if (alcoholStatusValue.HasFlag(Enums.Enums.AlcoholStatus.NonDrinker))
    {
        alcoholStatuses = string.Format("{0}{1}{2}", alcoholStatuses, (int)Enums.Enums.AlcoholStatus.NonDrinker, ",");
    }
    if (alcoholStatusValue.HasFlag(Enums.Enums.AlcoholStatus.NotRecorded))
    {
        alcoholStatuses = string.Format("{0}{1}{2}", alcoholStatuses, (int)Enums.Enums.AlcoholStatus.NotRecorded, ",");
    }

    return alcoholStatuses;
}