魚和熊掌不能兼得html
——中國諺語sql
Entity Framework做爲一個優秀的ORM框架,它使得操做數據庫就像操做內存中的數據同樣,可是這種抽象是有性能代價的,故魚和熊掌不能兼得。可是,經過對EF的學習,能夠避免沒必要要的性能損失。本篇只介紹關聯實體的加載的相關知識,這在我以前的文章中都有介紹。數據庫
咱們已經瞭解到EF的關聯實體加載有三種方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Loading都是延遲加載。框架
(一)Lazy Loading使用的是動態代理,默認狀況下,若是POCO類知足如下兩個條件,EF就使用Lazy Loading:性能
關閉Lazy Loading,能夠將LazyLoadingEnabled設爲false,若是導航屬性沒有標記爲virtual,Lazy Loading也是不起做用的。學習
(二)Eager Loading使用Include方法關聯預先加載的實體。spa
(三)Explicit Loading使用Entry方法,對於集合使用Collection,單個實體則使用Reference。代理
下面經過實例來理解這幾種加載方式。code
有下面三個實體:Province,City,Governor,一個Province有多個City,而且只有一個Governor。orm
1: public class Province
2: {
3: public int Id { get; set; }
4: public string Name { get; set; }
5:
6: public virtual Governor Governor { get; set; }
7:
8: public virtual List<City> Cities { get; set; }
9: }
10:
11: public class City
12: {
13: public int Id { get; set; }
14: public string Name { get; set; }
15: }
16:
17:
18: public class Governor
19: {
20: public int Id { get; set; }
21: public string Name { get; set; }
22: }
Lazy Loading
1: private static void LazyLoading(EFLoadingContext ctx)
2: {
3: //發送一條查詢到數據庫,查詢全部的province
4: var list = ctx.Provines.ToList();
5: foreach (var province in list)
6: {
7: //每次遍歷(用到導航屬性時)都發送2條查詢,一條查詢當前province包含的city和另外一條查詢當前province的governor
8: //若是ctx.Configuration.LazyLoadingEnabled爲false或者前者爲true,可是導航屬性沒有標註爲virtual,下面的操做都會拋出異常
9: Print(province);
10: }
11: }
Eager Loading
1: private static void EagerLoading(EFLoadingContext ctx)
2: {
3: //發送一條查詢到數據庫庫,查詢全部的province並關聯city和governor
4: var list = ctx.Provines.Include(t => t.Cities).Include(t => t.Governor);
5: foreach (var province in list)
6: {
7: //無論ctx.Configuration.LazyLoadingEnabled爲false,仍是沒有標註導航屬性virtual,都不會拋出異常
8: Print(province);
9: }
10: }
Explicti Loading
1: private static void ExplicitLoading(EFLoadingContext ctx)
2: {
3: //發送一條查詢到數據庫,查詢全部的province
4: var list = ctx.Provines.ToList();
5: foreach (var province in list)
6: {
7: var p = ctx.Entry(province);
8: //發送一條查詢,查詢全部當前province的city
9: p.Collection(t => t.Cities).Load();
10: //發送一條查詢,查詢當前province的governor
11: p.Reference(t => t.Governor).Load();
12: //無論ctx.Configuration.LazyLoadingEnabled爲false,仍是沒有標註導航屬性virtual,都不會拋出異常
13: Print(province);
14: }
15: }
Print方法
1: private static void Print(Province province)
2: {
3: Console.WriteLine("省:【{0}】,市:【{1}】,省長:【{2}】", province.Name, string.Join(",", province.Cities.Select(t => t.Name)), province.Governor.Name);
4: }
關於關聯加載實體基本上就是這些內容吧,若是想看這部分詳細的介紹,能夠參考我這篇文章的後半部分。總的來講,這部分比較簡單,一個LazyLoadingEnabled設置,三種加載方式。Lazy Loading會生成大量的sql,Eager Loading生成的關聯查詢比較負責,Explicit Loading同Lazy Loading同樣生成不少的sql,可是有一些其餘優勢,好比:導航屬性能夠不用標註爲virtual。若是這幾種關聯都不能解決實際問題,能夠直接使用sql查詢。
最後附上本文的demo,下載地址:http://pan.baidu.com/s/1i3IAiNF