來自:http://www.yaosansi.com/post/1388.html
首先,我們先來瞭解一些知識點。
1.匿名型別的傳遞
static void Main(string[] args)
{
var User = GetAnonymous().Cast(new { UserName = "", LastLoginIp = "" });
Console.Write(User.UserName);
}
static object GetAnonymous()
{
var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" };
return User;
}
當我們定義一個匿名型別,只能通過object類型傳遞,傳遞後編譯器將無法獲悉匿名型別的實際類型。
這行可以通過Cast擴充方法來進行強制轉換。以下是Cast方法的原型。
public static T Cast<T>(this object o, T t)
{
return (T)o;
}
2.如何產生匿名型別的List?
var User = GetAnonymous().Cast(new { UserName = "", LastLoginIp = "" });
var list = new List<???>();
原理和上面一致。
var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" };
var list = User.MakeList();
list.Add(User);
Console.Write(list[0].UserName);
我們再來看看MakeList()方法:
public static List<T> MakeList<T>(this T t)
{
return new List<T>();
}
當然,你可能想到上面的方法還不夠完美,需要在List中Add一個User,於是有了下面的方法:
public static List<T> MakeList<T>(this T t,params T[] items)
{
return new List<T>(items);
}
這時調用的時候可以寫成:
var User = new { UserName = "yaosansi", LastLoginIp = "127.0.0.1" };
var list = User.MakeList(User);
Console.Write(list[0].UserName);
這回我們切入正題,來瞭解一下LINQ中是怎樣多表查詢的。
var q =
from p in db.Products
where p.Supplier.Country == "USA" && p.UnitsInStock == 0
select p;
更多內容,請參考:部落格園 - 李永京- LINQ體驗(6)——LINQ to SQL語句之Join和Order By
以上的查詢是兩個有關係的表,並且返回的只是一個表的內容,
這種情況下可以在資料層中返回強型別的List。如:
public List<Products> SelectProducts()
{
var q =
from p in db.Products
where p.Supplier.Country == "USA" && p.UnitsInStock == 0
select p;
return q.ToList<Products>;
}
如果返回的結果集是兩個以上表的時候,那該如何傳遞呢?
聰明的你一定想到了,如果返回的是單行資料的結果集就可以我們前面提到的
使用 匿名型別的傳遞 得到我們需要的結果.
public object SelectProducts()
{
var q =
from p in db.Products
where p.Supplier.Country == "USA" && p.UnitsInStock == 0
select new {p.UnitsInStock,p.Supplier.Sid};
var result = q.Single();
return result;
}
但這個前提是商務邏輯層需要知道資料層的匿名型別中的具體類型。
這樣分層的意義也就不大了。這並不是我們想要的。
而且返回多行資料的結果集時用 匿名的List類型 的方法經實驗也失敗了。
這就意味著本文開篇的兩種傳遞匿名型別的方法都行不通。
方法一:
自訂與傳回型別相同結構的類,
public class CustomQuery
{
public uint UnitsInStock { get; set; }
public int Sid { get; set; }
}
這樣在查詢結果為多個表的結果集時,就可以解決了。
由於需要知道返回的匿名型別,除了不符合多層以外,還需要額外定義一個類。
但這樣確時可以使用強型別返回我們所需要的結果。
方法二:
使用System.Func委託 (參考:Returning var from a method in C# 3.0)
資料層:
public IEnumerable<TProjection> GetCustomersWithOrders<TProjection>(Func<Customer, IEnumerable<Order>, TProjection> projection) {
return from customer in _customers
let customerOrders = from order in _orders
where order.CustomerID = customer.ID
select projection(customer, customerOrders);
}
商務邏輯層:
var results = GetCustomersWithOrders((customer, orders) =>
new {
Name = customer.Name,
OrderCount = orders.Count()
});
這樣返回的結果在商務邏輯層裡仍然是真正的匿名型別,可以直接使用了。
方法三:
使用預存程序或視圖。