将大量数据转换为 C# 对象

Posted

技术标签:

【中文标题】将大量数据转换为 C# 对象【英文标题】:Converting a large set of data into C# objects 【发布时间】:2015-07-08 15:15:47 【问题描述】:

我正在制作一个复杂的应用程序(计划涉及:文章、销售、客户、制造、机器......),它使用 ERP 的 SQL Server 数据库提供的信息。

我使用了大约 30 个不同的相关对象,每个对象的信息都存储在表/视图中。其中一些表有 20k 到 100k 条记录。

我需要将所有这些表转换为 C# 对象以供将来处理,而这些表无法在 SQL 中处理。我不需要所有行,但没有办法确定我需要哪些行,因为这取决于运行时事件。

问题是关于执行此操作的最佳方法。我尝试了以下方法:

    检索所有数据并将其存储在 使用SqlDataAdapter 的数据集,它占用大约 300mb 的 RAM。 这里的第一个问题:同步,但它是可以接受的,因为数据不去 在执行过程中改变那么多。

    然后我遍历每一行并将其转换为C#对象, 存储在静态字典中,以便通过密钥快速访问。问题是创建这么多对象(数百万)占用了内存 使用量高达 1,4GB,这太多了。除了来自内存,数据 访问速度非常快。

因此,如果获取所有内容需要太多内存,我认为我需要某种延迟加载,所以我尝试了:

    我考虑过的另一个选项是直接查询数据库 通过SqlDataReader 过滤我需要的项目只有 第一次它是必需的,然后它存储在静态 字典。这种方式内存使用量是最低的,但是这种方式 速度很慢(按分钟排序),因为这意味着我需要进行一百万个服务器似乎不喜欢的不同查询(低性能)。

最后,我尝试了一种可行的中间方法,但我不确定它是否是最佳的,我怀疑它不是:

    第三种选择是填充包含所有信息的DataSet 并存储本地静态副本,但不将所有行转换为对象,只需按需执行(惰性),如下所示:

    public class ProductoTerminado : Articulo     
    
      private static Dictionary<string, ProductoTerminado> productosTerminados = new Dictionary<string, ProductoTerminado>();
    
      public PinturaTipo pinturaTipo  get; set; 
      public ProductoTerminado(string id)
          : base(id)  
      public static ProductoTerminado Obtener(string idArticulo)
      
          idArticulo = idArticulo.ToUpper();
          if (productosTerminados.ContainsKey(idArticulo))
          
            return productosTerminados[idArticulo];
          
          else
          
              ProductoTerminado productoTerminado = new ProductoTerminado(idArticulo);
              //This is where I get new data from that static dataset
              var fila = Datos.bd.Tables["articulos"].Select("IdArticulo = '" + idArticulo + "'").First();
              //Then I fill the object and add it to the dictionary.
              productoTerminado.descripcion = fila["Descripcion"].ToString();
              productoTerminado.paletizacion = Convert.ToInt32(fila["CantidadBulto"]);
              productoTerminado.pinturaTipo = PinturaTipo.Obtener(fila["PT"].ToString());
              productosTerminados.Add(idArticulo, productoTerminado);
              return productoTerminado;
          
       
    
    

那么,这是继续的好方法还是我应该研究实体框架或类似强类型的DataSet

【问题讨论】:

如果您有大量数据,也许您应该将其保留在数据库中(选项 2),而不是尝试在应用程序中创建本地内存数据库。当您的应用程序启动时,用户肯定不需要直接看到 1.4Gb 的数据?您的应用程序的主要数据感知屏幕上有什么?没有人能够理解网格中 1.4G 的数据。他们通常需要先分析它。也许你可以进一步解释 您没有说您的应用程序将如何使用,是有很多人同时访问数据,还是只有一两个人?该应用程序是从您的数据库位置远程使用还是在同一网络上使用?在选项 2 中,你说“程序很慢”,但你能量化你的意思吗?查询需要几秒钟、几分钟吗?如果没有其他信息,很难给出建议。 到目前为止我还不相信。它是基于集合的吗?您是否正在查找、交叉引用和汇总数据?当您只使用锤子时,一切看起来都像钉子(当然,它是双向的——我认为您可以在 SQL 中完成大多数事情,而不是自定义构建的应用程序层) 你把自己困在这里了。提出一个新问题,描述您要如何处理数据。 太宽泛了。数据处理性能取决于太多因素,无法给出粗略的答案。 【参考方案1】:

我使用大约 30 个不同对象之间的关系,每个对象的信息都存储在表/视图中。其中一些表有 20k 到 100k 条记录。

我建议对不同类型的对象做出不同的决定。通常,具有数千条记录的表更有可能发生更改。记录较少的表不太可能。在我正在处理的一个项目中,我决定在List&lt;T&gt; 中缓存不更改的对象(在启动时)。对于几百个实例,这应该不到一秒钟。

如果您使用 linq-to-sql,在 List&lt;T&gt; 中有一个本地对象并正确定义了 FK 约束,您可以执行 obj.Items 访问由 obj 的 ID 过滤的 Items 表。 (在本例中,obj 是 PK,Items 是 FK 表)。

这种设计还将为用户提供他们期望的性能。在处理小型集合时,一切都是即时的(缓存的)。在处理较大的集合但进行较小的选择或插入时 - 性能很好(使用 PK 的快速查询)。只有当您开始执行连接多个大表的查询时,您才会真正受苦;在这些情况下,用户可能会期待这一点(尽管如果不了解用例的更多信息,我无法确定)。

【讨论】:

以上是关于将大量数据转换为 C# 对象的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 转换为动态 C# 对象

怎样将json数据转换成匿名数组或者泛型对象(c#)

在 C# 中将数据表转换为 JSON

无法将“System.Object []”类型的对象转换为我的类 C#

在 C# 中将 SQL Datareader 转换为数据集

如何将内容不同但结构相同的 JSON 字符串转换为 C# 对象?