存储/检索位C#的最佳方式

本文关键字:最佳 方式 检索 存储 | 更新日期: 2024-10-22 23:07:07

我正在修改现有的C#解决方案,其中数据经过验证,状态存储如下:

a) 给定的记录是根据一定数量的条件(比如5)进行验证的。失败/通过状态由一个位值表示(0-通过;1-失败)b) 所以,如果一个记录在所有5次验证中都失败了,那么值将是11111。这将被转换为十进制并存储在数据库中。

再一次,这个十进制值将被转换回二进制(使用逐位&运算符),用于显示通过/失败的记录。

问题是,C#中使用了长数据类型来处理十进制,SQL Server 2008中使用了"decimal"数据类型来存储此十进制值。转换为二进制的long的最大值最多只能容纳64位,因此验证计数目前限制为64。

我的要求是取消这个限制,以允许任何数量的验证。

如何存储大量的位并检索它们?此外,请记住,这是一个现有的(.NET 2.0)解决方案,无法升级/使用任何第三方库,更改必须是最低限度的

最新更新

是的,从应用程序的角度来看,这个解决方案似乎是可以的,也就是说,如果只有我(也就是目前的解决方案)只使用C#。然而,现有解决方案的设计者将二进制值(11111表示所有5条记录失败,10111表示除第4条记录外的所有记录失败,依此类推…)存储在SQL Server数据库中,从而使事情变得复杂。SP使用此值得出每次验证失败的记录数。

OPEN sValidateCUR                        
 FETCH NEXT FROM sValidateCUR INTO @ValidationOID,@ValidationBit, @ValidationType            
 WHILE @@FETCH_STATUS = 0                        
 BEGIN                 
 -- Fetch the Error Record Count                
 SET @nBitVal = ABS(RPT.fGetPowerValue(@ValidationBit))  -- Validation bit is no. of a type of validation, say, e.g. 60. So 1st time when loop run, ValidationBit will be 0
select @ErrorRecordCount = COUNT(1) FROM 
 <<Error_Table_Where_Flags_are availble in decimal values>>
          WITH(NOLOCK) WHERE  ExpressionValidationFlags & CAST(CAST(@nBitVal AS VARCHAR(20)) AS Bigint) = CAST(@nBitVal AS VARCHAR(20)) -- For @ValidationBit = 3, @nBitVal = 2^3 = 8

现在,在应用程序中,使用BitArray,我设法将通过/失败的记录存储在BitArray中,将其转换为byte[],并以VARBINARY(100)的形式存储在SQL Server中。。。(同一列ExpressionValidationFlags,以前是BIGINT,现在是VARBINARY,并保存字节数组)。但是,为了完成我的更改,我需要修改上面的SP。

再次期待帮助!!

感谢

存储/检索位C#的最佳方式

为什么不使用专门设计的类BitArray

http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(System.Collections.BitArray);k(TargetFrameworkMoniker-.NETFramework,版本%3Dv4.5);k(DevLang-csharp)&rd=真实

例如

  BitArray array = new BitArray(150); // <- up to 150 bits
  ...
  array[140] = true;  // <- set 140th bit 
  array[130] = false; // <- reset 130th bit 
  ...
  if (array[120]) {   // <- if 120th bit is set
    ...

根据您使用的数据库的限制,有几种方法可以实现这一点。

如果能够在数据库中存储字节数组,则可以使用BitArray类。您可以向构造函数传递一个字节数组,使用它通过索引轻松检查和设置每个位,然后使用它的内置CopyTo方法将其复制回字节数组。

示例:

byte[] statusBytes = yourDatabase.Get("passed_failed_bits");
BitArray statusBits = new BitArray(statusBytes);
...
statusBits[65] = false;
statusBits[66] = true;
...
statusBits.CopyTo(statusBytes, 0);
yourDatabase.Set("passed_failed_bits", statusBytes);

如果数据库无法处理原始字节数组,则可以始终将字节数组编码为十六进制字符串:

string hex = BitConverter.ToString(statusBytes);
hex.Replace("-","");

然后再次将其返回到字节数组中:

int numberChars = hex.Length;
byte[] statusBytes= new byte[numberChars / 2];
for (int i = 0; i < numberChars; i += 2) {
    statusBytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}

如果你甚至不能存储字符串,有更具创造性的方法可以将字节数组转换为多个长或双。

此外,如果空间效率是一个问题,那么还有其他更有效(但更复杂)的方法可以通过使用更多的字符范围而不使用控制字符来将字节编码为ascii文本。如果您发现数据在长时间内保持不变,您可能还需要查看字节数组的Run Length Encoding。

希望这能有所帮助!

为什么不使用字符串?您可以在数据库中放入大量字符(使用VARCHAR而不是NVARCHAR,因为您可以控制输入)。

使用您的示例,如果您有"11111",您可以跳过按位操作,只做以下操作:

string myBits = "11111";
bool failedPosition0 = myBits[0] == '1';
bool failedPosition1 = myBits[1] == '1';
bool failedPosition2 = myBits[2] == '1';
bool failedPosition3 = myBits[3] == '1';
bool failedPosition4 = myBits[4] == '1';