Cast
的妙用:
泛用
LINQ
語句 文/黃忠成
什麼是泛用LINQ
語句 泛用LINQ語句的概念很簡單,在一些情況下,我們會有需求使用同一段程式碼來對不同資料表做查詢,這在ADO.NET中很容易達到,見下例:
| static void PrintCustomerID(SqlDataReader reader){ Console.WriteLine(reader.GetString(reader.GetOrdinal("CustomerID")));} |
此函式接受一個Reader物件,然後頃印CustomerID欄位值,這不受限於SqlDataReader所選取的Schema或是資料表,只要Schema中有CustomerID欄位即可。不過,這樣的手法在LINQ這種Typed-Query(具型別查詢語句)模式下,並沒有很直覺的寫法,因為你不能寫下下面的句子。
| static void Test2(int index){ var query; DataClasses1DataContext context = new DataClasses1DataContext(); context.Log = Console.Out; //for log only,you can remove it. if (index == 1) query = context.Customers; else query = context.Orders; var result = from s1 in query where s1.CustomerID.Contains("V") select s1; foreach (var item in result) { Console.WriteLine(item.CustomerID); }} |
編譯器會抱怨,var的變數必須在宣告時指定。那要如何在LINQ To SQL或是LINQ To Entites達到同樣的效果呢?這有幾個方法可以做到。
| 1、使用ExecuteQuery,並使用另一個Typed物件來接收回傳集。 |
| 2、使用實體類別(Entity Class)繼承。 |
| 3、使用Cast與partial class。 |
1與2對熟悉LINQ To SQL的讀者應該不難,所以我就不再贅述了,第三個手法是較少見的,我們可以運用partial class機制,讓Entity Classes實作特定介面,然後以Cast函式來達到目的。
| using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.Linq;using System.Data.SqlClient; namespace ConsoleApplication39{ class Program { static void Main(string[] args) { Test(1); Console.WriteLine("------"); Test(0); Console.ReadLine(); } static void Test(int index) { IQueryable<IGenericBaseClass> query = null; DataClasses1DataContext context = new DataClasses1DataContext(); context.Log = Console.Out; //for log only,you can remove it. if(index == 1) query = context.Customers.Cast<IGenericBaseClass>(); else query = context.Orders.Cast<IGenericBaseClass>(); var result = from s1 in query where s1.CustomerID.Contains("V") select s1; foreach (var item in result) { Console.WriteLine(item.CustomerID); } } } public interface IGenericBaseClass { string CustomerID { get; set; } } partial class Customers : IGenericBaseClass { } partial class Orders : IGenericBaseClass { }} |
仔細揣摩上面的程式碼,我相信你會找到一個不一樣的LINQ應用手法。