1. 程式人生 > 其它 >解決Entity Framework查詢匿名物件後的跨域訪問的一種方式

解決Entity Framework查詢匿名物件後的跨域訪問的一種方式

在Entity Framework中,可以使用lambda表示式進行對資料的查詢,而且可以將查詢結果直接對映為物件或者物件列表,這極大的提高的開發速度,並且使資料層的資料更加方便處理和傳遞。但是很多時候,我們不需要把整個表的欄位都查出來,如果我們直接把整個資料實體查詢出來,就極大的影響了效能,所以我們需要通過查詢匿名物件或者已經定義的方式,對資料庫進行查詢;

1.例項使用的資料實體類:

public  class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }

2.查詢

假設我們需要現實一個分類目錄,我們只需要Id和Name兩個欄位,我們可以建立一個新的CategoryView

public class CategoryView
{
    public int Id { get; set; }
    public string Name { get; set; }
}

查詢的時候,可以這樣做,讓它直接生成CategoryView的列表:

var data1 = from c in context.Categoriees
                select new CategoryView()
                {
                    Id = c.Id,
                    Name = c.Name
                };

這樣,可以在將方法返回值設定為IQueryable<CategoryView>型別,在呼叫方法處可以直接遍歷;

然而,當沒有CategoryView的時候,我們就只能使用匿名物件進行查詢:

var data = from c in context.Categoriees
                       select new
                       {
                           cId = c.Id,
                           cName = c.Name
                       };

這樣的查詢之後,同樣可以直接通過cId和cName取值,但是僅限當前方法內部,如果跨域訪問的話,就沒法直接讀出cId和cName的值了:

CategoryService類的實現如下所示:

namespace ConsoleApplication1
{
    public class CategoryService
    {
        private ShopContext context=new ShopContext();

        public IQueryable<object> GetAllCategories()
        {
            var data = from c in context.Categoriees
                       select new
                       {
                           cId = c.Id,
                           cName = c.Name
                       };
            return data;
        }
    }
}

呼叫方法:

CategoryService service=new CategoryService();
IQueryable<object> data = service.GetAllCategories();

這時,我們是沒法直接讀取object型別的屬性值的,在不考慮效能的前提下,我們可以使用反射,得到屬性值:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            CategoryService service=new CategoryService();
            IQueryable<object> data = service.GetAllCategories();
            foreach (var item in data)
            {
                Type type = item.GetType();
                PropertyInfo idProperty = type.GetProperty("cId");
                string id = idProperty.GetValue(item, null).ToString();
                PropertyInfo nameProperty = type.GetProperty("cName");
                string name = nameProperty.GetValue(item, null).ToString();

                Console.WriteLine("Id:"+id+" Name:"+name);
            }
            Console.ReadKey();
        }
    }
}

當然,這樣的操作,如果您覺得效能的問題不比需要建立CategoryView模型類造成的麻煩多的話,還是一種比較簡單快捷的實現方式,但是我的建議還是建立像CategoryView這樣的檢視模型類,可以發這個類物件傳遞給檢視直接顯示,何樂不為!!!

3.目前為止我所知的最好的跨域訪問方式

在c#4.0中,加入了dynamic特性,這使得我們可以使用它支援對動態型別的解釋,雖然c#語言絕對是靜態型別的,但是dynamic通過在編譯的時候,不推斷出具體型別,而是展開為表示式數的形式,在最後執行期間使用代理去執行呼叫的方法,是對匿名型別的呼叫比使用反射機制更加高效便捷了,所以,對於上述例項,可以使用如下方式進行呼叫:

foreach (dynamic item in data)
{
    Console.WriteLine(item.cId);
}

而我們失去的,只是visual studio的智慧提示而已,所以目前看來,這是最適當的一種方法,當然,如果是和UI層連結的服務層,我仍然推薦使用查詢ViewModel的方式