EF6.x 數(shù)據(jù)查詢

1. 基礎查詢

常見錯誤

  • EF 不支持Last或LastOrDefault
LastOrDefault
  • 量詞方法不支持實體類型的查詢陈哑,僅支持基本數(shù)據(jù)類型
    量詞方法包括:Contains距潘、Any磕谅、Exists/Not Exists等查詢方法点楼。
Contains
基本數(shù)據(jù)類型
  • Cast只能對基本類型進行映射或EDM原始類型糖儡;OfType可以對實體類型進行映射,但是不支持基本類型映射

不管哪種映射贷币,需要映射的類型需要保持一種繼承關系击胜。也就是在EF中主要用于繼承映射。

下面例子中:ManCustomers 繼承自 Customer役纹,但是映射失敗了偶摔。這是由于cast不支持實體類型映射

Cast映射復雜類型

將映射類型改為基本類型:


Cast映射基本類型

將映射類型改為EDM類型:


Cast映射EDM原始類型

OfType函數(shù)的轉(zhuǎn)換更加友好促脉,滿足條件才能進行轉(zhuǎn)換辰斋,起到過濾的作用,而Cast則是全盤轉(zhuǎn)換瘸味,若類型不匹配宫仗,則拋出異常。

OfType實體類型轉(zhuǎn)換
OfType不能轉(zhuǎn)換基本類型
  • 分頁查詢常見問題
沒有進行排序報錯

總結(jié):在使用EF進行分頁查詢時旁仿,未進行Order By排序的話锰什,會出現(xiàn)異常!EF不會自動生成Order By子句丁逝,并且上面的查詢會引發(fā)Not SupportedException異常汁胆。Order By 方法必須在Skip方法之前調(diào)用!

排序后進行分頁

當調(diào)用Take且沒有調(diào)用skip時霜幼,將被翻譯成top語句


沒有調(diào)用skip
生成的sql語句
  • Select 投影查詢嫩码,EF中不支持轉(zhuǎn)換為實體類型,僅支持轉(zhuǎn)換為原始類型罪既、匿名類型铸题。
不支持實體類型轉(zhuǎn)換

2. 加載關聯(lián)數(shù)據(jù)

1. Lazy Loading(延遲加載)

顧名思義,延遲加載就是當我們需要時才加載琢感,當?shù)谝淮卧L問指向?qū)嶓w/實體屬性時丢间,實體或?qū)嶓w集合將自動從數(shù)據(jù)庫加載。訪問導航屬性時驹针,相關對象/子對象不會自動加載烘挫。當使用POCO(Plain Old CLR Objects )實體類型時,通過創(chuàng)建派生代理類型的實例柬甥,然后覆蓋virtual 的導航屬性從而實現(xiàn)延遲加載饮六。
默認情況下,Entity Framework 啟用延遲加載苛蒲,但是我們可以在EF上下文派生類中手動關閉延遲加載卤橄。

public EfDbContext() : base("server=.;database=createDbContext;uid=sa;pwd=123123")
        {
            Database.SetInitializer(new CreateDatabaseIfNotExists<EfDbContext>());
            Configuration.LazyLoadingEnabled = false;//關閉延遲加載
        }

延遲加載的數(shù)據(jù),只有真正使用的時候才會去查詢數(shù)據(jù)庫進行加載顯示臂外。

延遲加載需要注意問題:

  • 循環(huán)引用
    當A表中有B表的導航屬性窟扑,并且B表中由于A表的導航屬性喇颁,那么在進行延遲加載的時候就會出現(xiàn)序列化循環(huán)引用問題。
    解決方法: 通過投影來解決序列化循環(huán)引用問題嚎货。

延遲加載的本質(zhì):只有當調(diào)用者使用時才會計算結(jié)果橘霎。

2. Eager Loading(饑餓加載)

查詢時提示,加載相關實體/子實體作為查詢的一部分厂抖,加載父對象時同時加載子對象茎毁,在EF中,我們可使用DbSet<T>.Include()方法來實現(xiàn)饑餓加載忱辅,和延遲加載不同的是七蜘,饑餓加載時,無論我們用火不用墙懂,利用Include()方法都會對子對象進行加載橡卤。

var customer=db.Customers.Include("Orders").FirstOrDefault();

其中Include()方法中的字符串參數(shù)是其關聯(lián)的導航屬性。

3. Explicitly Loading(顯示加載)

延遲執(zhí)行有延遲加載和顯示加載兩種方式损搬,即使我們僅用了延遲加載碧库,仍然可以通過顯示加載來延遲加載相關實體。通過DbEntityEntry<T>.Reference("").Load()加載實體巧勤,通過DbEntityEntry<T>.Collection("").Load()加載集合嵌灰。

顯示加載的本質(zhì):即使金庸延遲加載依然可以延遲執(zhí)行。

3. 原始查詢

EF底層還是Ado.net,對于一些復雜的查詢颅悉,我們還是需要利用原始查詢或者存儲過程來完成沽瞭。在EF中,我們可以通過SqlQuery方法來進行原始查詢剩瓶,SqlQuery方法有如下2中形式:

efDbContext.Database.SqlQuery<TElement>(string sql, params object[] parameters);
efDbContext.Customers.SqlQuery<TElement>(string sql, params object[] parameters);
  • 在實體上執(zhí)行原始查詢

原始查詢只有當結(jié)果全部枚舉玩(也就是只有ToList后)才會與數(shù)據(jù)庫進行交互驹溃,否則將不會執(zhí)行查詢。

                var c1=db.Database.SqlQuery<Customer>("select * from Customers").ToList();
                c1.FirstOrDefault().Name = "c1";
                db.SaveChanges();
                var c2=db.Customers.SqlQuery("select * from Customers").ToList();
                c2.Last().Name = "c2";
                db.SaveChanges();
修改結(jié)果

分析:
當我們在上下文構(gòu)造函數(shù)中關閉變更追蹤時延曙,第一種形式將不會更新到數(shù)據(jù)庫豌鹤,所以只是執(zhí)行查詢時,直接使用第一種SqlQuery實現(xiàn)即可枝缔。這是由于SqlQuery方法實體查詢是在數(shù)據(jù)庫Database上布疙,實體不會被上下文跟蹤。魂仍;第二種方法不但執(zhí)行了查詢而且還執(zhí)行了修改操作拐辽。這是由于SqlQuery方法實體查詢在上下文中的實體集合DbSet上,實體被上下文跟蹤擦酌。

查詢指定列

利用SqlQuery查詢實體時必須返回所有列,否則將拋出異常菠劝,這是利用SqlQuery進行查詢的最大缺點赊舶。

  • 返回自定義類型執(zhí)行原始查詢

  • 在非實體上執(zhí)行原始查詢

ctx.Database.SqlQuery<TEntity>():SqlQuery方法支持返回單條記錄。
ctx.Set<TEntity>().SqlQuery():SqlQuery方法不支持返回單條記錄

  • 傳遞參數(shù)執(zhí)行原始查詢

字符串拼接:

var id = 2; 
var customers = db.Database.SqlQuery<Customer>($"select * from customers where id={id}").ToList();

參數(shù)化:

                var name = "張三";
                var parameters = new SqlParameter[]
                {
                    new SqlParameter(){ParameterName="@id",SqlDbType=System.Data.SqlDbType.Int,Value=id}
                };
                var c = db.Database.SqlQuery<Customer>("select * from customers where id=@id",parameters).ToList();
  • 利用原始查詢執(zhí)行存儲過程

var c = db.Database.SqlQuery<Customer>("GetCustomers");
  • 利用原始查詢執(zhí)行存儲過程傳遞參數(shù)

var parameters = new SqlParameter("@id", 2);
var c = db.Database.SqlQuery<Customer>("GetCustomers",parameters);

注意:調(diào)用存儲過程時,如果數(shù)據(jù)庫時SqlServer2005笼平,就需要在存儲過程前加上Exec园骆,否則會拋出異常。

  • 執(zhí)行增刪改操作

當需要執(zhí)行增刪改操作時寓调,我們需要使用Database對象上的ExecuteSqlCommand或者ExecuterSqlCommandAsync方法锌唾。和SqlQuery查詢一樣,ExecuteSqlCommand或者ExecuterSqlCommandAsync也有2個參數(shù)夺英。

                string sql = @"INSERT INTO [dbo].[Customers]
                                    ([Name]
                                    ,[Email]
                                    ,[CreateTime]
                                    ,[ModifiedTime])
                                VALUES
                                    (@name
                                    ,@email
                                    ,@CreateTime
                                    ,@ModifiedTime)";
                var parameters = new SqlParameter[] {
                    new SqlParameter("@name","養(yǎng)老四"),
                    new SqlParameter("@email","324@21.com"),
                    new SqlParameter("@CreateTime","2019-04-06 10:42:29.243"),
                    new SqlParameter("@ModifiedTime","2019-04-06 10:42:29.243"),
                };
                db.Database.ExecuteSqlCommand(sql, parameters);
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晌涕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子痛悯,更是在濱河造成了極大的恐慌余黎,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件载萌,死亡現(xiàn)場離奇詭異惧财,居然都是意外死亡,警方通過查閱死者的電腦和手機扭仁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門垮衷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人乖坠,你說我怎么就攤上這事搀突。” “怎么了瓤帚?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵描姚,是天一觀的道長。 經(jīng)常有香客問我戈次,道長轩勘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任怯邪,我火速辦了婚禮绊寻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘悬秉。我一直安慰自己澄步,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布和泌。 她就那樣靜靜地躺著村缸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪武氓。 梳的紋絲不亂的頭發(fā)上梯皿,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天仇箱,我揣著相機與錄音唠雕,去河邊找鬼丐膝。 笑死秸仙,一個胖子當著我的面吹牛默蚌,可吹牛的內(nèi)容都是我干的阎毅。 我是一名探鬼主播矮烹,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼罐呼,長吁一口氣:“原來是場噩夢啊……” “哼捣染!你這毒婦竟也來了冤议?” 一聲冷哼從身側(cè)響起斟薇,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎求类,沒想到半個月后奔垦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡尸疆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年椿猎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寿弱。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡犯眠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出症革,到底是詐尸還是另有隱情筐咧,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布噪矛,位于F島的核電站量蕊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏艇挨。R本人自食惡果不足惜残炮,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缩滨。 院中可真熱鬧势就,春花似錦、人聲如沸脉漏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侧巨。三九已至舅锄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間司忱,已是汗流浹背巧娱。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工碉怔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烘贴,地道東北人禁添。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像桨踪,于是被迫代替她去往敵國和親老翘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容