天天看點

LINQ to CSV,一種類型安全,動态的高性能方法介紹背景使用代碼輸入CSV檔案設計動機類型安全——運作時類型安全檢查改變自我,動态類型優缺點與性能  檔案夾結構簡短的代碼演練限制和假設結論

目錄

介紹

背景

使用代碼

輸入CSV檔案

設計動機

類型安全——運作時類型安全檢查

改變自我,動态類型

優缺點與性能  

檔案夾結構

簡短的代碼演練

限制和假設

結論

下載下傳完整的源代碼

介紹

語言內建查詢(LINQ)為查詢以各種形式存儲的資料對象提供了出色的接口。LINQ to SQL,LINQ to objects,LINQ to XML都是一些例子。LINQ提供了查詢任何類型資料源的通用接口。由于LINQ查詢已內建到C#語言中,是以可以加速開發。本文是關于LINQ to CSV(逗号分隔)檔案資料的方法。

背景

主要設計目标是促進業務應用程式的快速開發。假設您有一個包含業務資料的CSV檔案。您需要編寫功能,比如Business_Feature1使用此資料來提供聚合。現在,在一兩天内開發這樣的Business_Feature1并不是很困難。然後,幾天後又說,你需要寫一個Business_Feature2使用另一個CSV檔案來提供最暢銷的區域。同樣的,開發人員需要再花費1或2天時間來開發此功能。最聰明的方法是在開發Business_Feature1過程中分離關注點。那就是,Business_Feature1是作為兩個子產品開發的。子產品1使用CSV檔案将其轉換為對象,而子產品2對這些對象執行業務操作以提供整潔的業務功能。這很可能需要相同的時間。但是,如果采用這種智能方法,開發Business_Feature2就會變得很快,隻需幾個小時。這是因為來自Business_Feature1的子產品1重新用于快速應用程式開發。這不僅縮短了開發時間,還提高了産品品質。由于子產品1經曆了嚴格的測試階段,是以更加穩定且無錯誤。

現在,有了這個背景,下圖說明了可重用子產品,子產品1作為C#經典語言功能之一的LINQ。然後,業務功能的開發不會花費數小時,而是需要幾分鐘,因為您需要編寫的隻是一個簡單的LINQ查詢來獲得所需的功能開發。

其他LINQ 2 csv與此庫的比較

LINQ to CSV,一種類型安全,動态的高性能方法介紹背景使用代碼輸入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

鑒于我們手中有LINQ to CSV庫,這項任務隻需要幾分鐘的開發時間。這是因為這個開發所需的行數隻有1行,即1個LINQ查詢,如下所示:

//  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檔案的内容,以檢視示例輸出如何改變以響應您的更改。

示例輸出如下所示:

LINQ to CSV,一種類型安全,動态的高性能方法介紹背景使用代碼輸入CSV檔案設計動機類型安全——運作時類型安全檢查改變自我,動态類型優缺點與性能  檔案夾結構簡短的代碼演練限制和假設結論

設計動機

主要設計目标是促進快速業務應用程式開發。為了實作這一設計目标,類似用例中常見的軟體元件被精确地分離為可重用子產品。這使開發團隊能夠專注于開發業務功能,同時樣闆闆子產品已準備就緒。

資料從csv檔案加載到C#動态對象。這部分是樣闆元件,可以重複使用。CSV檔案内容作為對象數組加載到記憶體中,CSV标頭作為對象屬性,即item[0].gross_profit将擷取數組中的第一個對象,屬性名為gross_profit。隻需一行C#LINQ查詢即可輕松開發業務功能。該子產品基本上是LINQ for CSV檔案。新功能開發涉及為業務案例編寫LINQ查詢。

  • 分析了Pure LINQ與Hybrid LINQ之間的優缺點(參見優缺點部分)
  • 基于接口的設計,用于更清晰的抽象
  • 通用的足以處理任何帶标題的CSV檔案
  • CSV檔案作為對象數組加載,具有要操作的對象的成員屬性。這樣就可以在這些對象上編寫LINQ查詢。

類型安全——運作時類型安全檢查

該庫完全是類型安全的,并檢查CSV中的每個元素以確定類型安全。如果發現類型安全不比對,則抛出異常。這有助于使用者在處理查詢結果時立即處理問題,而不是錯誤的資料或異常。是的,請記住,LINQ是非常延遲的綁定,同時處理查詢結果。  

這是CSV檔案将類型資訊饋送到linq2csv庫的方式

LINQ to CSV,一種類型安全,動态的高性能方法介紹背景使用代碼輸入CSV檔案設計動機類型安全——運作時類型安全檢查改變自我,動态類型優缺點與性能  檔案夾結構簡短的代碼演練限制和假設結論

改變自我,動态類型

在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 LINQ與Hybrid LINQ之間的優缺點。Pure LINQ被稱為實作LINQ to CSV功能的純LINQ擴充功能。混合LINQ被稱為通過動态對象實作LINQ to CSV功能。采用混合LINQ方法的原因如下:
    • 純LINQ需要為每個查詢加載CSV檔案,而混合LINQ将CSV檔案加載到記憶體中一次,以用于所有查詢
    • 由于純LINQ查詢中的“C#閉包”問題,純LINQ效率低,而混合方法沒有閉包問題
  • 使用.NET并行庫的快速CSV檔案閱讀器
  • log4net,使用第三方記錄器。Log4net功能豐富,适合此類項目
  • LINQ的使用有助于提高性能,因為可以避免不必要的記憶體配置設定。查詢結果僅在讀取時獲得。

在使用大多數内置LINQ功能時,編寫新的LINQ擴充保持在最低限度。

檔案夾結構

主檔案夾包含bin,doc,sample,source和specification。顧名思義,每個目錄都包含适當的内容。規範目錄包含需求文檔。

  • 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))  
               };
           

這裡,dataToOperate是CSV閱讀器公開的資料結構。此資料按國家/地區分組。然後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