LINQ to CSV,一种类型安全,动态的高性能方法

目录

介绍

背景

使用代码

输入CSV文件

设计动机

类型安全——运行时类型安全检查

改变自我,动态类型

优缺点与性能  

文件夹结构

简短的代码演练

扫描二维码关注公众号,回复: 5347311 查看本文章

限制和假设

结论


下载完整的源代码

介绍

语言集成查询(LINQ)为查询以各种形式存储的数据对象提供了出色的接口。LINQ to SQLLINQ to objectsLINQ to XML都是一些例子。LINQ提供了查询任何类型数据源的通用接口。由于LINQ查询已集成到C#语言中,因此可以加速开发。本文是关于LINQ to CSV(逗号分隔)文件数据的方法。

背景

主要设计目标是促进业务应用程序的快速开发。假设您有一个包含业务数据的CSV文件。您需要编写功能,比如Business_Feature1使用此数据来提供聚合。现在,在一两天内开发这样的Business_Feature1并不是很困难。然后,几天后又说,你需要写一个Business_Feature2使用另一个CSV文件来提供最畅销的区域。同样的,开发人员需要再花费12天时间来开发此功能。最聪明的方法是在开发Business_Feature1过程中分离关注点。那就是,Business_Feature1是作为两个模块开发的。模块1使用CSV文件将其转换为对象,而模块2对这些对象执行业务操作以提供整洁的业务功能。这很可能需要相同的时间。但是,如果采用这种智能方法,开发Business_Feature2就会变得很快,只需几个小时。这是因为来自Business_Feature1的模块1重新用于快速应用程序开发。这不仅缩短了开发时间,还提高了产品质量。由于模块1经历了严格的测试阶段,因此更加稳定且无错误。

现在,有了这个背景,下图说明了可重用模块,模块1作为C#经典语言功能之一的LINQ。然后,业务功能的开发不会花费数小时,而是需要几分钟,因为您需要编写的只是一个简单的LINQ查询来获得所需的功能开发。

其他LINQ 2 csv与此库的比较

使用代码

这个LINQ to CSV库的主要优点是,开发人员根本不需要编写任何特殊代码。他们可以在项目中导入库linq2csv,只需将LINQ查询写入CSV文件即可。所有数据绑定都是运行时发生的。

包含一个示例项目以使用此库(Linq2CSV)。假设我们有一个如下所示的CSV文件。地区,NA是北美。我们的业务目标是按地区查找净利润。

输入CSV文件

区域

国家

帐户ID

货币

毛利

税率

NA

USA

1

USD

1234232.76

10

NA

Canada

2

CAN

453232.4576

10

APAC

Hong Kong

3

HKD

124342.1

1

EMEA

Saudi Arabia

4

SAR

2345234535

0

鉴于我们手中有LINQ to CSV库,这项任务只需要几分钟的开发时间。这是因为这个开发所需的行数只有1行,即1LINQ查询,如下所示:

//  Method signature looks like public IEnumerable<dynamic> GetNetProfitByRegionUSD()
//  LINQ query 
 result = from data in dataToOperate
        group data by ((dynamic)data).region
        into profitByRegion
        select new
        {
          Region = profitByRegion.Key,
          NetProfitUSD = profitByRegion.SumOfDecimals(dataItem => 
          {
            decimal netProfit = 0.0M;
            decimal tax = 0.0M;
            if (((dynamic)dataItem).gross_profit > 0)
             tax = ((dynamic)dataItem).gross_profit * 
                               (((dynamic)dataItem).tax_rate / 100.0M);

             netProfit = ((dynamic)dataItem).gross_profit - tax;

             return netProfit * ((dynamic)dataItem).conversion_factor;
            })
        };
//

如果您熟悉LINQ,这看起来很简单。

根据本文中给出的CSV文件输入,输出如下所示:

### Total Net Profit (Tax deducted) by Region in USD ###
 Region : NA |  NetProfitUSD : 127285002.6245864620 |
 Region : APAC |  NetProfitUSD : 27333822.56032211400 |
 Region : EMEA |  NetProfitUSD : 1259879792.90627115830 |
 Region : APC |  NetProfitUSD : 434647.7561869611525 |

从上面的链接(本文顶部)下载示例以查看快速运行输出。您可以更改CSV文件的内容,以查看示例输出如何改变以响应您的更改。

示例输出如下所示:

sample output

设计动机

主要设计目标是促进快速业务应用程序开发。为了实现这一设计目标,类似用例中常见的软件组件被精确地分离为可重用模块。这使开发团队能够专注于开发业务功能,同时样板板模块已准备就绪。

数据从csv文件加载到C#动态对象。这部分是样板组件,可以重复使用。CSV文件内容作为对象数组加载到内存中,CSV标头作为对象属性,即item[0].gross_profit将获取数组中的第一个对象,属性名为gross_profit。只需一行CLINQ查询即可轻松开发业务功能。该模块基本上是LINQ for CSV文件。新功能开发涉及为业务案例编写LINQ查询。

  • 分析了Pure LINQHybrid LINQ之间的优缺点(参见优缺点部分)
  • 基于接口的设计,用于更清晰的抽象
  • 通用的足以处理任何带标题的CSV文件
  • CSV文件作为对象数组加载,具有要操作的对象的成员属性。这样就可以在这些对象上编写LINQ查询。

类型安全——运行时类型安全检查

该库完全是类型安全的,并检查CSV中的每个元素以确保类型安全。如果发现类型安全不匹配,则抛出异常。这有助于用户在处理查询结果时立即处理问题,而不是错误的数据或异常。是的,请记住,LINQ是非常延迟的绑定,同时处理查询结果。  

这是CSV文件将类型信息馈送到linq2csv库的方式

Type Safety Info

改变自我,动态类型

C#中,动态类型将在运行时解析。动态类型在运行时根据RHS(右侧)的类型更改其类型。例如,在下面的代码:

dynamic runTimeType = "Hello World";

Console.Writeline("Type of runTimeType: {0}", runTimeType.GetType().ToString());

这将打印System.String

如果将任何类分配给动态类型,编译器将不检查方法、属性或对象上的任何操作的正确性。这是因为这在运行时得到解决。动态类型在Visual Studio IDE中不支持智能感知。但是,尽管没有进行编译时检查,但如果方法或属性不正确,则抛出运行时异常。

优缺点与性能  

  • 与其他LINQ to CSV库不同,您甚至不需要编写单行代码来使用CSV文件。您可以导入库并在CSV文件中编写LINQ查询目标内容。所有绑定都在运行时神奇地发生
  • 分析了Pure LINQHybrid LINQ之间的优缺点。Pure LINQ被称为实现LINQ to CSV功能的纯LINQ扩展功能。混合LINQ被称为通过动态对象实现LINQ to CSV功能。采用混合LINQ方法的原因如下:
    • LINQ需要为每个查询加载CSV文件,而混合LINQCSV文件加载到内存中一次,以用于所有查询
    • 由于纯LINQ查询中的C#闭包问题,纯LINQ效率低,而混合方法没有闭包问题
  • 使用.NET并行库的快速CSV文件阅读器
  • log4net,使用第三方记录器。Log4net功能丰富,适合此类项目
  • LINQ的使用有助于提高性能,因为可以避免不必要的内存分配。查询结果仅在读取时获得。

在使用大多数内置LINQ功能时,编写新的LINQ扩展保持在最低限度。

文件夹结构

主文件夹包含bindocsamplesourcespecification。顾名思义,每个目录都包含适当的内容。规范目录包含需求文档。

  • Bin - 发布和调试配置中的二进制文件
  • 示例 - 发布和调试模式下的工作示例程序
  • 源代码 - 库的源代码,示例程序和单元测试
  • 规范 - 要求文件
  • Readme.docx - 提供项目详细信息的文件

简短的代码演练

这是代码的主要功能部分。令人惊讶的是,只需一行代码即可完成业务需求。

按国家/地区划分的总利润总额的一行LINQ查询:

result = from data in dataToOperate
                group data by ((dynamic)data).country
                into profitByCountry
                select new
                {
                    Country = profitByCountry.Key,
                     GrossProfitUSD =
                     profitByCountry.SumOfDecimals(item =>
                    ((dynamic)item).gross_profit *(((dynamic)item).conversion_factor))  
               };

这里,dataToOperateCSV阅读器公开的数据结构。此数据按国家/地区分组。然后Total使用SumOfDecimals方法添加。使用转换率将毛利转换为美元。

限制和假设

以下是此模块的假设和限制:

  • 税率的计算没有任何特定于国家/地区的税收规定或规则。
  • 对于亏损账户(即负利润账户),税率计算为零。
  • 不检查输入CSV文件项的类型安全性,但需要。在CSV文件中给出类型信息时,可以添加此功能。
  • CSV文件内容的修改不会在运行时流向输出结果集。

即使实现了类型安全,它也是运行时而不是编译时安全。这是因为我们在运行时获取输入数据(CSV文件)。

结论

这是一个有趣的模块,它使用C#语言最好的功能之一LINQ。该模块可以轻松扩展到CSV数据的实时显示,能够将LINQ用于任何底层数据结构,类型安全检查,运行时查询(来自配置文件,用户输入等)。以类似的方式,IOutput接口可以扩展为支持html5推送数据,文本输出,胖客户端的自定义输出。

 

原文地址:https://www.codeproject.com/Articles/1276238/LINQ-to-CSV-A-Dynamic-High-Performance-Approach

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/87969610
今日推荐