如何将带有数组的C#对象存储到数据库中?

3
我目前正在使用C#开发一款软件,并希望将数据存储在数据库中。我的问题是,我正在寻找最佳方法来存储包含两个数组的对象的数据。数组中的对象看起来完全相同,但它们具有不同的含义。
作为信息:数据对象的数据经常变化。
例如,我有以下两个类:
public class ObjectA
{
    public string Text { get; set; }
    public int Value { get; set; }
}

public class ObjectB
{
    public string Text { get; set; }
    public int Value { get; set; }
}

public class ObjectC
{
    public string Name { get; set; }
    public List<ObjectA> DetailsA { get; set; }
    public List<ObjectB> DetailsB { get; set; }
}

请注意,我目前从ObjectC中获取了超过24000个对象。每个对象数组包含的对象数量可能会有很大差异(最多可达200甚至更多)。如果我使用其中一种解决方案,是否会出现任何最大行数方面的问题?

我考虑了以下两种数据库架构:

  1. All attributes in one table.

    Create a coloumn for each attribute of ObjectA and ObjectB so that i can store each object in the array in one row.

    CREATE TABLE `data` (
      `data_id`     INT            NOT NULL,
      `name_a`      NVARCHAR(50)   NOT NULL,
      `text_a`      NVARCHAR(100)  NOT NULL,
      `name_b`      NVARCHAR(50)   NOT NULL,
      `text_b`      NVARCHAR(100)  NOT NULL,
      `value`       INT            NOT NULL,
      PRIMARY KEY (`data_id`)
    )
    

    In this case i would store the value of name redundantly.

  2. Creating a foreign key in the table for ObjectA

    By doing this i could avoid storing the data from ObjectC redundantly while having to use joins when querying the data.

    CREATE TABLE `data` (
      `data_id`     INT            NOT NULL    AUTO_INCREMENT,
      `name`        NVARCHAR(50)   NOT NULL,
      PRIMARY KEY (`data_id`)
    )
    
    CREATE TABLE `details_a` (
      `a_id`        INT            NOT NULL    AUTO_INCREMENT,
      `text`        NVARCHAR(100)  NOT NULL,
      `value`       INT            NOT NULL,
      `data_fk`     INT            NOT NULL,
      PRIMARY KEY (`a_id`)
    )
    
    CREATE TABLE `details_b` (
      `b_id`        INT            NOT NULL    AUTO_INCREMENT,
      `text`        NVARCHAR(100)  NOT NULL,
      `value`       INT            NOT NULL,
      `data_fk`     INT            NOT NULL,
      PRIMARY KEY (`b_id`)
    )
    
此外,每当数组数据发生变化时,是创建数据库中的新行更好,还是更改现有数据?编辑:增加了一些关于对象数量的信息(在c#示例正下方)。

4
第三种方法是使用一个鉴别器列并将A和B存储在同一个数据库表中——鉴别器告诉你它是A还是B。通常/惰性的做法是使用/配置ORM映射器来为您完成此操作,因此您可以将您的数据库视为C#对象,让ORM映射器处理细节(例如EntityFramework、Hibernate、code-first、data-first等,这里有一个例子:https://msdn.microsoft.com/en-us/library/jj200620(v=vs.113).aspx)。顺便说一下,第一种方法不能用于As或Bs的列表——您至少需要第二个版本与外键一起使用。 - Patrick Artner
将其编码为JSON,然后将其放入TEXT列中。 - Rick James
将数据存储为JSON的优势是什么? - Fabian S.
2个回答

2

顺便说一下,方法1不能与A或B列表一起使用 - 您至少需要使用第二个版本的fks。

使用连接是不错的选择,数据库规范化也很好。它将您的数据分区,并允许数据库更好地优化查询。

第三种方法是使用一个描述器列将A和B存储在同一个数据库表中 - 描述器告诉您它是A还是B。

CREATE TABLE `details_ab` (
  `a_id`        INT            NOT NULL    AUTO_INCREMENT,
  `text`        NVARCHAR(100)  NOT NULL,
  `value`       INT            NOT NULL,
  'isA'         BIT            NOT NULL,   -- True == A else B 
  `data_fk`     INT            NOT NULL,
  PRIMARY KEY (`a_id`)
)

通常/懒惰的方法是使用/配置ORM映射器来处理这个问题,这样您就可以将您的数据库视为C#对象,并让ORM映射器处理细节(例如:Google EntityFramework、Hibernate、Code-First、Data-First等,详见此处:msdn.microsoft.com/en-us/library/jj200620(v=vs.113).aspx)。


至于插入或更新——这取决于情况。如果您必须(例如出于法律或保险原因)在您的数据库中拥有完整的数据记录,则可以使用一个表并始终仅插入——然后在其上创建一个视图,以显示数据项的“最新”版本。

例如,每行都有一个ID,您有一个“BusinessID”,用于唯一标识“一个对象”——您第一次插入它,然后修改它:这会将其作为具有新DB-ID和相同“BusinessID”的记录插入。您在表上创建一个视图,该视图仅显示每个BusinessID的最高DB-ID(假设为整数DB-ID)。您的表中保存了整个历史记录,但您的应用程序“通常”只看到视图,但管理员可能会访问整个表而不是视图……等等。


在这里讨论的鉴别器列方法的另一个好处是为未来提供了灵活性。如果您想在未来添加第三个详细类型,此方法使得进行这样的更改变得相当微不足道。至于ORM映射器,我有一点小意见,我不认为它们是“懒惰”的方法。要正确使用它们,您真的需要先了解您的模式,因此我认为它们并没有简化数据库设计工作;ORM映射器只是在数据层和业务层之间交流时让生活变得更加轻松而已。无论有没有ORM,一个设计不良的模式都是一场噩梦。 - Kevin Fichter
我忘了提到我需要处理多少个对象(不知道这个信息有多相关,但以防万一)。我已经相应地编辑了我的帖子。 - Fabian S.
如果您有许多大表格,请为服务器添加更多的RAM和SSD - 对于少于几百万行的表格,我不会花太多时间考虑。在长表中查找内容是数据库的工作。 - Patrick Artner

0

使用外键创建表结构可能是最好的解决方案,也是最常见的实现方式。但是,我知道根据使用情况需求可能会有所不同,因此这里提供一种可能的替代方案。

根据使用情况和大小,我发现将对象和变量存储为XML序列化等效项在数据库中非常有用。如果您只需要它进行持久性存储,那么这是最简单的方法,然后您可以通过一个简单的表保存时间戳和XML对象来保存版本控制。在紧急情况下,您甚至可以使用SQL查询您的XML对象以访问数据或者在以后需要更改存储方法时进行迁移。我使用这种方法来存储具有不同数据类型的字典样式数据,以便在单个表中快速访问环境变量。


我从未在Sql中使用过XML(除了通常需要在2008r2早期用于分组文本的STUFF .. FROM XML)。您能否高效地执行xmldata上的join / avg / sum等操作? - Patrick Artner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接