我有一个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,"
答案 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;
}