如何在 Postgres 中正确存储 C# 的位数组 table
How to correctly store C#'s Bitarray in Postgres table
目前我正在尝试在 Postgres table 中存储可变长度的位模式。我的用例是我想以紧凑的方式对有关分配给组的数据记录的一些信息进行编码。
我的 table 在 Postgres 中的简化架构如下所示:
CREATE TABLE axivas.group_records (
id int4 NOT NULL GENERATED ALWAYS AS IDENTITY,
record_id int4 NOT NULL,
group_ids varbit(50) NOT NULL,
CONSTRAINT group_records_pkey PRIMARY KEY (id));
在 C# 应用程序中,我使用 Npgsql Entity FrameworkCore 创建实体,如下所示:
try
{
var context = new xerxesdevtestsContext();
Random rnd = new Random();
for (int i = 0; i < 1024; i++)
{
BitArray ba = new BitArray(rnd.Next(10, 50));
ba.SetAll(false);
for (int j=rnd.Next(0,5);j<rnd.Next(5,ba.Length-1);j++)
{
ba[j] = true;
}
context.GroupRecords.Add(new GroupRecords()
{
GroupIds = ba,
RecordId = i
});
}
context.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
在 porpose 上添加了随机数,用于设置位数和位数组的长度。
当我查看存储的数据时,我可以看到在某些情况下,位字符串以前导零存储,而在其他情况下,前导零被省略(我附上了 screenshot 来说明这一点)。换句话说,在某些情况下,DBeaver 会显示类似“0000110110111110000.....”的值,在其他情况下会显示类似“1100111...”的值。
所以我的问题是,如何解释这一点,是否可以完全省略位串中的前导零?
如有任何想法或额外信息,我们将不胜感激。
更新:
我更改了 table 和
中位串的大小
将位数组中的各个位设置位并再次测试的算法。我的更改具有以下效果:
- 位数组将从最高索引开始填充。
- 在结果事件中可以观察到更多的前导零;例如这是结果记录之一:
|3104 |702 |0000000000000000000000000000000000000000000000000000000000000000000000111111111111111111110 |
我认为这种情况清楚地表明了为什么我要省略前导零。
此致,
迈克尔
您的位数组具有前导零的原因似乎很明显,因为在您的 for
循环中,j
被初始化为某个很少为零的值。 j
必须始终为零才能开始在数组的开头放置 1。否则,在大多数情况下,您将以前导零结尾。
所以,如果你想要可变长度的随机二进制数,为什么不这样做:
BitArray ba = new BitArray(rnd.Next(10, 50));
ba.SetAll(false);
ba[0] = true;
for (int j = 1; j < ba.Length - 1; j++)
{
ba[j] = Convert.ToBoolean(rnd.Next(2));
}
创建的示例值:
100110101001000011111100110100010101100110110
111101100110001101001100111101001100011110
1010101111000100
1011001010001000010100
101001101001010100101110000001000111001010
目前我正在尝试在 Postgres table 中存储可变长度的位模式。我的用例是我想以紧凑的方式对有关分配给组的数据记录的一些信息进行编码。
我的 table 在 Postgres 中的简化架构如下所示:
CREATE TABLE axivas.group_records (
id int4 NOT NULL GENERATED ALWAYS AS IDENTITY,
record_id int4 NOT NULL,
group_ids varbit(50) NOT NULL,
CONSTRAINT group_records_pkey PRIMARY KEY (id));
在 C# 应用程序中,我使用 Npgsql Entity FrameworkCore 创建实体,如下所示:
try
{
var context = new xerxesdevtestsContext();
Random rnd = new Random();
for (int i = 0; i < 1024; i++)
{
BitArray ba = new BitArray(rnd.Next(10, 50));
ba.SetAll(false);
for (int j=rnd.Next(0,5);j<rnd.Next(5,ba.Length-1);j++)
{
ba[j] = true;
}
context.GroupRecords.Add(new GroupRecords()
{
GroupIds = ba,
RecordId = i
});
}
context.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
在 porpose 上添加了随机数,用于设置位数和位数组的长度。
当我查看存储的数据时,我可以看到在某些情况下,位字符串以前导零存储,而在其他情况下,前导零被省略(我附上了 screenshot 来说明这一点)。换句话说,在某些情况下,DBeaver 会显示类似“0000110110111110000.....”的值,在其他情况下会显示类似“1100111...”的值。
所以我的问题是,如何解释这一点,是否可以完全省略位串中的前导零?
如有任何想法或额外信息,我们将不胜感激。
更新: 我更改了 table 和
中位串的大小将位数组中的各个位设置位并再次测试的算法。我的更改具有以下效果:
- 位数组将从最高索引开始填充。
- 在结果事件中可以观察到更多的前导零;例如这是结果记录之一:
|3104 |702 |0000000000000000000000000000000000000000000000000000000000000000000000111111111111111111110 |
我认为这种情况清楚地表明了为什么我要省略前导零。
此致,
迈克尔
您的位数组具有前导零的原因似乎很明显,因为在您的 for
循环中,j
被初始化为某个很少为零的值。 j
必须始终为零才能开始在数组的开头放置 1。否则,在大多数情况下,您将以前导零结尾。
所以,如果你想要可变长度的随机二进制数,为什么不这样做:
BitArray ba = new BitArray(rnd.Next(10, 50));
ba.SetAll(false);
ba[0] = true;
for (int j = 1; j < ba.Length - 1; j++)
{
ba[j] = Convert.ToBoolean(rnd.Next(2));
}
创建的示例值:
100110101001000011111100110100010101100110110
111101100110001101001100111101001100011110
1010101111000100
1011001010001000010100
101001101001010100101110000001000111001010