在数据库中存储Dictionary 或KeyValuePair

我想看看其他人在处理List 或Dictionary 等类型时遇到了什么,并反过来存储和检索这些数据?

这是一个示例场景:用户将创建自己的“模板”,其中这些模板本质上是Dictionary的集合,例如对于user1,值为(1,Account),(2,Bank),(3,Code),( 4,Savings),对于user2,值(不相关)可以是(1,Name),(2,Grade),(3,Class)等。 这些模板/列表的长度可能不同,但它们始终具有索引和值。 此外,每个列表/模板将只有一个用户链接到它。

您在数据库方面选择了哪些类型?

我应该注意的痛点和/或建议?

就集合中的类型而言,.Net类型和SQL类型之间存在相当一对一的映射: SQL Server数据类型映射 。 您最需要担心字符串字段:

  • 它们总是ASCII值(0 – 255)吗? 然后使用VARCHAR 。 如果它们可能包含非ASCII / UCS-2字符,则使用NVARCHAR
  • 他们可能的最大长度是多少?

当然,有时您可能希望在数据库中使用稍微不同的数字类型。 主要原因是如果在应用程序端选择了一个int ,因为它比Int16byte “更容易”(或者我被告知)处理,但是值永远不会超过32,767或255,那么你应该最多可能分别使用SMALLINTTINYINT 。 应用层内存中intbyte之间的差异可能很小,但它确实会对物理存储产生影响,尤其是在行数增加时。 如果不清楚,“影响”意味着减慢查询速度,有时需要购买更多SAN空间时需要花费更多资金。 但是,我之所以“ 最有可能使用SMALLINTTINYINT ”的原因是因为如果你有Enterprise Edition并且启用了行压缩或页面压缩,那么这些值将存储在它们适合的最小数据类型中。

至于从数据库中检索数据,这只是一个简单的SELECT

至于存储这些数据(至少在有效地做到这一点),那么,这更有趣:)。 将字段列表传输到SQL Server的一种好方法是使用表值参数(TVP)。 这些是在SQL Server 2008中引入的。我在这个答案中发布了一个代码示例(C#和T-SQL),这里有一个非常相似的问题:将Dictionary 传递给存储过程T-SQL 。 该问题还有另一个TVP示例(接受的答案),但它不使用IEnumerable ,而是使用DataTable ,它是集合的不必要副本。

编辑:关于最近更新的问题,指定实际数据被持久化,应该存储在类似于以下的表中:

 UserID INT NOT NULL, TemplateIndex INT NOT NULL, TemplateValue VARCHAR(100) NOT NULL 

PRIMARY KEY应该是(UserID,TemplateIndex),因为它是一个独特的组合。 IDENTITY字段不需要(至少没有给定的信息)。

TemplateIndexTemplateValue字段将在TVP中传递,如我在上面链接的问题的答案中所示。 UserID将作为第二个SqlParameter自行发送。 在存储过程中,您将执行类似于以下操作的操作:

 INSERT INTO SchemaName.TableName (UserID, TemplateIndex, TemplateName) SELECT @UserID, tmp.TemplateIndex, tmp.TemplateName FROM @ImportTable tmp; 

并且只是明确说明,除非有一个非常具体的理由这样做(这需要包括永远,不需要在任何查询中使用这些数据,这样这些数据实际上只是一个文档而且不再可用于查询而不是PDF或图像),那么你不应该将它序列化为任何格式。 虽然如果你倾向于这样做,XML是比JSON更好的选择,至少对于SQL Server来说,因为内置支持在SQL Server中与XML数据交互,但对JSON没有那么多。

列表或任何集合在数据库中的表示应该是表。 始终将其视为一个集合,并将其与数据库提供的内容联系起来。

虽然你总是可以序列化一个集合,但我不建议更新或插入记录,你总是更新整个记录或数据,而有一个表,你只需要查询KEY其中的Dictionary,你已经有了它。