1

以这种情况为例:您在 C# 中有一些标志枚举与 SQL Server 中的 Enum-ish 表相关联(实际上是从这些表生成的)。假设您是分销商,并且您允许您的经销商指定他们运送到美国的哪个州。作为一名出色而优雅的软件工程师,您将这些实现为可按位组合的标志值以节省存储空间:

create table USState (
    StateID bigint, StateAbbr char(2), StateName varchar(50))
/* insert all US States + DC into USState, StateIDs must be in powers of two */ 
/* StateID 0 reserved for 'None': */
create procedure GetStatesByFlag (@StateFlags bigint) as
declare @StateIDs table
(
StateID bigint,
primary key (StateID)
)
insert into @StateIDs 
    select StateID 
    from USState
    where @StateFlags & StateID != 0
        or (@StateFlags = 0 and StateID = 0)

select s.StateID, s.StateAbbr, s.StateName 
from 
    USState s join 
    @StateIDs si 
    on si.StateID = s.StateID

甜的。您可以使用按位逻辑在 SQL 和 C# 中动态包含/排除,这使您可以立即在 Asp.NET 中混合复选框列表和选择列表,同时仍然只存储一个 64 位数字来保存任何选择组合。并且您不需要在过程的 WHERE 子句中使用不可索引的比较运算符,除非枚举表本身最多具有 64 行。在您的分销商中搜索运往印第安纳州和加利福尼亚州的每个人仍然可以使用平等比较和索引。

现在,您请求添加对美国领土、武装部队邮件代码和加拿大省份的支持,并以向后兼容的方式执行此操作。没有将列表减少到 < 64 个条目,并且该企业确实希望避免将老派州与其他地区和部门隔离开来。

你做什么工作?

创造性的答案值得赞赏,但这里真正的挑战是:有没有办法强制在无符号 64 位值上工作的相同按位数学在使用负空间超过 64 位可能的位时,在 C#和 SQL (2008)?如果重要,该标志是模拟的,而不是“真实”标志,因此从技术上讲,它不需要针对具有 [Flags] 属性的 CLR 枚举。

4

3 回答 3

5

64 位值不能超过 64 位,甚至不能使用“负空间”。如果你有 64 位,你就有 64 位。您可以使用 Guid 来获取 128 位,这将暂时解决问题,但最终您将需要添加其他字段。

于 2009-11-14T00:49:39.740 回答
3

在 SQL Server 中,您可以尝试 decimal(38,0)

这为您提供了小数点左侧 38 位 (1E38)。在二进制方面,它大约是 126 位 (8.5E37)。它可以像数字一样被操纵。

但是,一种选择是在 .NET 中定义您想要的内容,并在 SQL Server 中使用匹配的CLR 数据类型。这样,它可以在 2 个平台之间保持一致。

但是,我真的会考虑改变旗帜......

于 2009-11-14T09:07:48.147 回答
1

我的 2c:你试图变得聪明,你自己造成了痛苦。位域和 SQL 不能很好地混合,主要是因为位域不能正确索引,并且任何搜索都必须进行完整扫描。例如。要查找所有发往 AK 的经销商,您需要扫描整个经销商表。此外,该解决方案不会扩展到超过 64 个值(正如您已经发现的那样)。它的存储选择也很差,它需要一个值为 0 的位来存储负面信息(缺乏关联)。

使用单独的表格来模拟经销商与他们运送到的州/地区/省/国家之间的多对多关系。

于 2009-11-14T19:23:42.963 回答