如何在数据库中存储带有数组的c#对象?

时间:2018-01-04 23:48:09

标签: c# mysql arrays database-design

我目前正在使用C#开发一个软件,并希望它将数据存储在数据库中。我的问题是我正在寻找存储包含两个数组的对象数据的最佳方法。数组中的对象看起来完全相同,但它们有不同的含义。

作为信息:数据中对象的数据正在定期更改。

例如,我得到以下两个classe:

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个,将来可能更多)。如果我使用其中一个解决方案,这会导致最大行数的问题吗?

我对数据库shema的外观有两个看法:

  1. 一个表中的所有属性。

    ObjectAObjectB的每个属性创建一个coloumn,以便我可以将数组中的每个对象存储在一行中。

    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`)
    )
    

    在这种情况下,我会冗余地存储name的值。

  2. 在ObjectA的表中创建外键

    通过这样做,我可以避免在查询数据时必须使用连接时冗余地存储来自ObjectC的数据。

    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`)
    )
    
  3. 另外,每次数组数据发生变化时,最好在数据库中创建一个新行,还是应该更改现有数据呢?

    编辑:添加了一些有关对象数量的信息(在c#示例的正下方)。

2 个答案:

答案 0 :(得分:2)

(从评论转到回答,太长了)

方法1不适用于As或Bs btw的列表 - 至少你需要第二个版本的fks。

使用连接很好,数据库规范化也很好。它对您的数据进行分区,并允许数据库更好地优化查询。

作为第三种方法,您可以使用descriminator-column并将A和B存储在同一个dbtable中 - 鉴别器会告诉您它是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,代码优先, data-first,fe here:msdn.microsoft.com/en-us/library/jj200620(v=vs.113).aspx)。

至于插入或更新 - 取决于。如果你必须(合法地为fe或保险)必须在你的数据库中拥有完整的数据系列,你可以使用一个表,并且只插入 - 并且顶部有一个视图,它覆盖了数据项目的“最新”版本。 / p>

即。每一行都有一个ID,你有一个“BusinessID”,它为你唯一标记“一个对象” - 你第一次插入它,然后你修改它:这将插入一个新的DB-Id和相同的“BusinessID”。您在表上创建一个仅显示每个BusinessID的最高DB-ID的视图(假设整数DB-Ids)。您在表中拥有完整的历史记录,但您的应用程序“通常”只能看到视图,但管理员可能可以访问整个表而不是视图...等等。

答案 1 :(得分:0)

使用外键创建表结构可能是最好的解决方案,它将是最常用的。也就是说,我知道需求会根据使用情况而有所不同,所以这是一种可能的选择。

根据用途和大小,我发现在DB中将对象和变量存储为XML序列化等价物会很有帮助。如果您只需要持久存储,那么这是最简单的方法,然后您可以使用包含时间戳和XML对象的简单表来保存版本控制。在紧要关头,您甚至可以使用SQL查询XML对象以访问数据,或者在以后需要更改时迁移存储方法。我使用这种方法在单个表中存储具有不同数据类型的字典样式数据,以便快速访问环境变量。