目錄
介紹
背景
使用代碼
輸入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庫的主要優點是,開發人員根本不需要編寫任何特殊代碼。他們可以在項目中導入庫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檔案的内容,以檢視示例輸出如何改變以響應您的更改。
示例輸出如下所示:
設計動機
主要設計目标是促進快速業務應用程式開發。為了實作這一設計目标,類似用例中常見的軟體元件被精确地分離為可重用子產品。這使開發團隊能夠專注于開發業務功能,同時樣闆闆子產品已準備就緒。
資料從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庫的方式
改變自我,動态類型
在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