将大量数据转换为 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<T>
中缓存不更改的对象(在启动时)。对于几百个实例,这应该不到一秒钟。
如果您使用 linq-to-sql,在 List<T>
中有一个本地对象并正确定义了 FK 约束,您可以执行 obj.Items
访问由 obj
的 ID 过滤的 Items 表。 (在本例中,obj 是 PK,Items 是 FK 表)。
这种设计还将为用户提供他们期望的性能。在处理小型集合时,一切都是即时的(缓存的)。在处理较大的集合但进行较小的选择或插入时 - 性能很好(使用 PK 的快速查询)。只有当您开始执行连接多个大表的查询时,您才会真正受苦;在这些情况下,用户可能会期待这一点(尽管如果不了解用例的更多信息,我无法确定)。
【讨论】:
以上是关于将大量数据转换为 C# 对象的主要内容,如果未能解决你的问题,请参考以下文章