2012年3月28日 星期三

Dynamic LINQ + Entity Framework - Part.2:Dynamic Expression API (NuGet)


上一篇「Dynamic LINQ + Entity Framework - Part.1:MS SQL Server, LINQPad」我們說到了可以將 VS2010 Sample Code 的 DynamicQuery 加入到專案中,

讓我們的專案可以使用字串的方式讓原本強型別的 LINQ Query 能夠動態組合,用比較方便、簡單的方式來解決動態柴詢條件的需求,

必須要先說明的是,這樣的動態查詢就失去了在設計階段時的強制檢查,當動態組成的查詢條件有錯誤時,就必須等到執行階段才會知道,在專案建置時是無法發現到錯誤,

所以在專案中使用 LINQ DynamicQuery 時必須要小心,不要因為可以動態的組合查詢而讓各種可能發生錯誤的可能因素到處流竄,

盡可能限縮組合動態查詢的條件,例如物件屬性(對應到資料庫表格的欄位)就盡可能使用列舉的方式,讓程式開發人員只能使用物件中的屬性名稱,另外輸入的條件值也必須要做點安全性的防護,

前面幾項說明是提醒各位使用 DynamicQuery 時所要注意的地方。

前一篇所使用的是 VS2010 的 C# 4.0 Sample Code,所以對於仍使用 .Net 3.5 的專案就必須要另外去使用 VS2008 Sample Code 來建立 for .Net 3.5 的 DynamicQuery 類別庫專案,

如果你不想自己去建立 DynamicQuery 類別庫專案的話,開發環境是在 VS2010,不管專案是用 .NET 4.0 或 .NET 3.5,

都可以從 NuGet Gallery 中去把 DynamicQuery 給加入到專案中。

 


NuGet - Dynamic Expression API 1.0

有位 bigsan 將 .NET 3.5 的 DynamicQuery 做了 NuGet Package,所以可以不用自己去建立一個 DynamicQuery 的類別庫專案,

http://nuget.org/packages/DynamicQuery

image

不過要注意的是,這個 NuGet Package 的最後更新時間是 2011-01-12,而 VS2008 C# SmapleCode 的最後更新日期已經到了 2011-11-29,

我並沒有仔細比較兩個有什麼樣的差異,而在功能使用上,我也沒有做比較詳細的測試比較,這個 Dynamic Expression API 還是可以使用的,

不放心的人,可以自行前往下載 VS2008 C# Sample Code 然後再手動做成類別庫專案,

Official Visual Studio 2008 C# Samples
http://code.msdn.microsoft.com/csharpsamples

P.S. 如果你的開發環境還是使用 VS2008 的話,也不用擔心無法使用 Nuget,

可以參照 Scott Hanselman 所寫的一篇文章「NuGet Support for Visual Studio 2008

依照文章中的操作後就可以在 VS2008 中使用 NuGet 的支援囉。

 


於 VS2010 透過 NuGet 為專案加入 Dynamic Expression API

我這邊就不說明怎麼在 VS2010 中開啟 NuGet,

開啟 Nuget 之後,輸入「DynamicQuery」搜尋,會找到「Dynamic Expression API」的項目,

找到之後就直接按「Install」安裝。

image

 

安裝完成之後可以檢查一下專案中的「參考」目錄,會看到有多出一個「Dynamic」的組件,

image

也可以開啟專案中的「packages.config」文件檔案,可以看到透過 NuGet 所加入的參考組件,

image

另外,透過 NuGet 所加入的組件,並不會把 dll 檔案給放置到專案本身的 bin 目錄中,

而是會另外放在專案外一個名稱為「packages」的目錄之中,

image

「packages > DynamicQuery.1.0」的目錄中有兩個子目錄,分別是「content」「lib」,

「content」目錄中所放置的就是「Dynamic Expression.html」說明文件,

image

「lib > 35」目錄下所放置的就是「Dynamic.dll」

image

 

在 VS2010 中所開發的專案如果要使用這個 DynamicQuery,

務必在檔案中加入 namespace「System.Linq.Dynamic」,不然程式是無法使用 DynamicQuery 的功能,

image

 


在 LINQPad 中測試使用 Dynamic Expression API

還先不急著說明怎麼在 VS2010 裡的專案去使用 Dynamic Expression API,先說明如何在 LINQPad 中去使用,

因為很多時候會需要在 LINQPad 中去測試 LINQ Query 語法,上一篇有說明過如果在 LINQPad 中加入組件參考,並且加入 namespace 的使用,並且設為啟動時的預設,

而上面也跟大家說透過 NuGet 所加入組件的目錄位置,所以下面就簡單的以圖示來說明如何加入組件與命名空間,

 

加入組件參考

1. 點選「Browse」以瀏覽參考組件的檔案位置

2. 選擇「packages > DynamicQuery.1.0 > lib > 35」目錄下的「Dynamic.dll」檔案

3. 加入「Dynamic.dll」

SNAGHTML6664eb

 

加入 Namespace 的使用

於文字輸入框裡面填入「System.Linq.Dynamic」,輸入完成後可以點選「Set as default for new queries」,

讓後續新增的 Query Tab 都預設使用組件參考與命名空間。

SNAGHTML693cb3

 

 

於 LINQPad 中測試 DynamicQuery

測試一:

SNAGHTML6ee7ff

查詢結果:

image

SQL Command:

SELECT 
[Extent1].[CategoryID] AS [CategoryID], 
[Extent1].[CategoryName] AS [CategoryName], 
[Extent1].[Description] AS [Description], 
[Extent1].[Picture] AS [Picture]
FROM [dbo].[Categories] AS [Extent1]
WHERE [Extent1].[CategoryName] LIKE N'%a%'
ORDER BY [Extent1].[CategoryID] ASC

 

測試二:

SNAGHTML715948

查詢結果:

image

SQL Command:

SELECT TOP (10) 
[Project1].[CustomerID] AS [CustomerID], 
[Project1].[CompanyName] AS [CompanyName], 
[Project1].[ContactName] AS [ContactName], 
[Project1].[ContactTitle] AS [ContactTitle], 
[Project1].[Address] AS [Address], 
[Project1].[City] AS [City], 
[Project1].[Region] AS [Region], 
[Project1].[PostalCode] AS [PostalCode], 
[Project1].[Country] AS [Country], 
[Project1].[Phone] AS [Phone], 
[Project1].[Fax] AS [Fax]
FROM ( SELECT 
    [Extent1].[CustomerID] AS [CustomerID], 
    [Extent1].[CompanyName] AS [CompanyName], 
    [Extent1].[ContactName] AS [ContactName], 
    [Extent1].[ContactTitle] AS [ContactTitle], 
    [Extent1].[Address] AS [Address], 
    [Extent1].[City] AS [City], 
    [Extent1].[Region] AS [Region], 
    [Extent1].[PostalCode] AS [PostalCode], 
    [Extent1].[Country] AS [Country], 
    [Extent1].[Phone] AS [Phone], 
    [Extent1].[Fax] AS [Fax], 
    (SELECT 
        COUNT(1) AS [A1]
        FROM [dbo].[Orders] AS [Extent2]
        WHERE [Extent1].[CustomerID] = [Extent2].[CustomerID]) AS [C1]
    FROM [dbo].[Customers] AS [Extent1]
)  AS [Project1]
WHERE (N'London' = [Project1].[City]) AND ([Project1].[C1] >= 10)
ORDER BY [Project1].[CustomerID] DESC

 


這一篇先說明如何建立一個 .NET 3.5 的 DynamicQuery 類別庫專案,也另外介紹了透過 NuGet 加入 DynamicQuery 組件參考(Dynamic Expression API 1.0),

然後也稍稍說明如何在 LINQPad 中去加入透過 NuGet 所增加的組件以及加入命名空間的使用,

由於 NuGet 上面的「Dynamic Expression API 1.0」是產生於 .NET 3.5 的 Sample Code,所以適合仍使用 .Net 3.5 的專案,

如果專案所使用的 .Net Framework 版本為 4.0,那麼我真的建議各位直接取用 VS2010 C# Sample Code 中的 DynamicQuery,並且自行建立為類別庫專案,以方便日後的重複使用。

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。