Entity Framework 4 in Action读书笔记——第三章:查询对象模型基础(1)
本章要點(diǎn):
1.EF查詢技術(shù)。
2.捕捉生成的SQL。
3.深入理解EF查詢引擎。
4.常見(jiàn)的查詢陷阱。
一、查詢引擎入口點(diǎn)
對(duì)象服務(wù)層最重要的類是ObjectContext。在你的代碼中它是最有用的類,因?yàn)樗峁┝宋ㄒ坏膱?zhí)行LINQ to Entities查詢的入口點(diǎn)。Visual Studio設(shè)計(jì)器的一個(gè)特征就是生成實(shí)體類,這些類繼承自O(shè)bjectContext并且每個(gè)實(shí)體類(有些例外)有一個(gè)集合屬性,表示實(shí)體集。可以把實(shí)體集理解為數(shù)據(jù)庫(kù),實(shí)際上它并不存儲(chǔ)數(shù)據(jù),而是對(duì)它查詢。后邊會(huì)看到對(duì)實(shí)體集的查詢?nèi)绾巫兂蒘QL并返回?cái)?shù)據(jù),現(xiàn)在暫且把注意力放在實(shí)體集上。
表示實(shí)體集的屬性是ObjectSet<T>類型的。在OrderIT中,這個(gè)屬性是Orders,類型為ObjectSet<Order>,下面是它的定義。
public partial class OrderITEntities : ObjectContext {private ObjectSet<Order> _orders;public ObjectSet<Order> Orders{get { return _orders ?? (_orders = CreateObjectSet<Order>("Orders")); }} }ObjectSet<T>繼承自O(shè)bjectQuery<T>。ObjectQuery<T>是在EF 1.0時(shí)用的類,ObjectSet<T>與ObjectQuery<T>保持兼容性的同時(shí)又新加了一些方便的方法。ObjectContext不是抽象的。向?qū)梢粋€(gè)繼承自O(shè)bjectContext專門(mén)的類的唯一原因是自動(dòng)生成實(shí)體集屬性加上一些輔助方法。生成的類是完美的,應(yīng)該經(jīng)常使用它。
如果有一種情況,你不能使用它,你可以通過(guò)傳連接字符串名稱直接實(shí)例化ObjectContext類。然后,就可以使用CreateObjectSet<T>方法,將實(shí)體集的名稱作為參數(shù)創(chuàng)建ObjectSet<T>實(shí)例。下面是代碼:
using (ObjectContext ctx = new ObjectContext("name=ConnStringName")) {var os = ctx.CreateObjectSet<Order>("Orders"); }如你所看,手動(dòng)創(chuàng)建一個(gè)ObjectSet<T>實(shí)例一點(diǎn)都不難。
當(dāng)實(shí)例化設(shè)計(jì)器產(chǎn)生的上下文類,不需要傳連接字符串給構(gòu)造器,然而直接對(duì)ObjectContext操作就必須傳一個(gè)連接字符串了。設(shè)計(jì)器知道連接字符串是什么,當(dāng)模板生成上下文類使,它創(chuàng)建了調(diào)用基類構(gòu)造器的構(gòu)造器,連接字符串傳給基類構(gòu)造器。上下文類中得構(gòu)造器如下面片段所示:
public OrderITEntities() : base("name=ConnStringName") { }二、設(shè)置連接字符串
你已經(jīng)看到,連接字符串對(duì)ObjectContext來(lái)說(shuō)是強(qiáng)制性的。如何傳遞連接字符串在EF Framework和ADO.NET Framework中有細(xì)微的不同,在EF中必須給連接字符串加一個(gè)Name=前綴:Name=ConnStringName。跟過(guò)去相比,這不是唯一的不同。連接字符串本身很古怪,下面的代碼就是OrderIT配置文件中的連接字符串。
<add name="OrderITEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=OrderIT;persist security info=True;user id=sa;password=sa;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />跟以前相比,結(jié)構(gòu)是相同的,但是數(shù)據(jù)是以不同的方式組織起來(lái)的。name表示連接字符串的名稱,它在上下文類中傳遞給構(gòu)造器。connectionString跟以前見(jiàn)過(guò)的有很大的不同,可能看起來(lái)還有點(diǎn)糊涂。但是必須得理解它,因?yàn)楫?dāng)修改數(shù)據(jù)庫(kù)時(shí)必須修改它。它分為三部分:
metadata —指定三個(gè)映射文件的位置,以”|”分割。如果文件作為純文本存儲(chǔ)在硬盤(pán)中,就指定文件的路徑;如果文件作為資源存儲(chǔ)在程序集中,就使用如下的規(guī)定格式:res://*/filename。
provider —為數(shù)據(jù)庫(kù)指定ADO.NET不變的數(shù)據(jù)提供程序名稱,就好像將providerName填入connectionString節(jié)中。
provider connection string —表示連接數(shù)據(jù)庫(kù)的真實(shí)字符串。如果包含雙引號(hào),必須使用它的轉(zhuǎn)義格式",避免與XML格式發(fā)生沖突。
最后是providerName包含System.Data.EntityClient字符串,它是不變的EF數(shù)據(jù)提供程序的名稱。
設(shè)置連接字符串是一項(xiàng)很重要的工作。幸運(yùn)的是,它是由設(shè)計(jì)器完成的,只有在更改數(shù)據(jù)庫(kù)時(shí)才會(huì)觸碰它。如果在運(yùn)行時(shí)動(dòng)態(tài)構(gòu)建,可以使用EntityConnectionStringBuilder類。
在代碼中創(chuàng)建連接字符串
通常連接字符串放在配置文件中由程序讀取。然后,在一些情況下,需要在運(yùn)行時(shí)改變連接字符串。第一種情況字符串的每個(gè)屬性由一個(gè)服務(wù)返回,這不是最好的架構(gòu),但是有時(shí)必須使用它。第二種情況,應(yīng)用程序需要處理兩個(gè)不同版本的SQL Server(2005和2008),這意味著有兩個(gè)不同的SSDL文件,合適的一個(gè)應(yīng)該是由程序運(yùn)行是根據(jù)數(shù)據(jù)庫(kù)的版本選擇的。有兩個(gè)解決方案:
1.手動(dòng)創(chuàng)建字符串構(gòu)建連接字符串。
2.運(yùn)行時(shí)使用EntityConnectionStringBuilder構(gòu)建連接字符串。
不用說(shuō),第二種解決方案是更好的選擇。
EntityConnectionStringBuilder類繼承自ADO.NET基礎(chǔ)類DbConnectionStringBuilder,它負(fù)責(zé)從一組參數(shù)構(gòu)建一個(gè)連接字符串和解析一個(gè)給定的連接字符串成單獨(dú)參數(shù)。下表描述了它的屬性。
在描述的第一種情況,可以使用DbConnectionStringBuilder類從一個(gè)單獨(dú)的參數(shù)產(chǎn)生一個(gè)連接字符串。你可以從Web服務(wù)中取得Metadata, Provider和Provider-ConnectionString參數(shù),使用它們?cè)O(shè)置連接字符串并且傳遞給上下文類的構(gòu)造器,如下所示:
var connStringData = proxy.GetConnectionStringData(); var builder = new EntityConnectionStringBuilder(); builder.Provider = connStringData.Provider; builder.Metadata = connStringData.Metadata; builder.ProviderConnectionString = connStringData.ProviderConnectionString; using (var ctx = new OrderITEntities(builder.ConnectionString)) {... }重要的是數(shù)據(jù)里不能包含節(jié)的名稱。例如provider參數(shù)必須包含值System.Data.SqlClient,而不是Provider=System.Data.SqlClient,Provider=會(huì)由EntityConnectionStringBuilder類自動(dòng)進(jìn)行處理。
第二種情況,在運(yùn)行時(shí)構(gòu)建連接字符串,只需要改變連接字符串的一部分:SSDL的位置。這種情況下,可以將連接字符串放在配置文件中看,在SSDL位置放一個(gè)占位符{0}。一旦知道數(shù)據(jù)庫(kù)的版本就可以用合適的SSDL路徑替換占位符。這可以用簡(jiǎn)單的String.Format完成,但是EntityConnectionStringBuilder能夠連接字符串并填入相關(guān)的屬性。
下面的解決方案首先加載連接字符串,然后使用String.Format只修改Metadata屬性。
var builder = new EntityConnectionStringBuilder(); builder.ConnectionString = connString; builder.Metadata = String.Format(builder.Metadata, "res://*/Model.ssdl"); using (var ctx = new OrderITEntities(builder.ConnectionString)) {... }連接字符串只是第一部分,在第一章提到EF最主要的特征是對(duì)對(duì)象模型查詢而不是對(duì)數(shù)據(jù)庫(kù),下一篇我們把主要精力放在對(duì)象模型查詢上。
轉(zhuǎn)載于:https://www.cnblogs.com/nianming/archive/2011/08/18/2144964.html
總結(jié)
以上是生活随笔為你收集整理的Entity Framework 4 in Action读书笔记——第三章:查询对象模型基础(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 蘑菇街怎么入驻商家
- 下一篇: 实况足球19a和19b有什么区别 《实况