新聞中心
.NET框架4.0的發(fā)行推出了許多優(yōu)秀的增強(qiáng)功能,其中當(dāng)首推ADO.NET實(shí)體框架。該框架已經(jīng)克服了以前的許多錯誤,并提供了一組增強(qiáng)的API,其中包括許多新的LINQ to SQL框架方面的改善。在本文中,我們將使用這些API的功能來創(chuàng)建一個通用版本的數(shù)據(jù)倉庫。

成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),民勤企業(yè)網(wǎng)站建設(shè),民勤品牌網(wǎng)站建設(shè),網(wǎng)站定制,民勤網(wǎng)站建設(shè)報價,網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,民勤網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
一、實(shí)體框架概述
實(shí)體框架針對數(shù)據(jù)模型提供了一些更方便的操作方法。默認(rèn)情況下,設(shè)計器可以生成一個描述數(shù)據(jù)庫的模型。
盡管表格間的映射未必都是1:1的映射。每個表格使用一個ObjectSet加以描述,進(jìn)而ObjectSet對象又提供了相應(yīng)的方法來創(chuàng)建、更新或反射實(shí)體和實(shí)體間的關(guān)系。實(shí)體框架使用一個實(shí)體鍵(這是一個看上去像EntitySet=Customers;CustomerID=4的值)來唯一標(biāo)識模型內(nèi)的一個實(shí)體及其標(biāo)識符。使用實(shí)體鍵,我們就有了一個方法來更新對象、從數(shù)據(jù)庫中查詢的對象,等等。
二、創(chuàng)建和更新
讓我們首先來看一個基類示例倉庫的實(shí)現(xiàn)。我想分別地討論CRUD操作,首先來學(xué)習(xí)創(chuàng)建和更新操作。
清單1:創(chuàng)建/更新操作
- public abstract class BaseRepository
: IRepository - where T : EntityObject
- {
- public virtual bool CreateNew(T entity)
- {
- if (entity == null)
- throw new ArgumentNullException("entity");
- var ctx = CreateContext();
- try
- {
- ctx.AddObject(this.GetFullEntitySetName(ctx), entity);
- ctx.SaveChanges();
- return true;
- }
- catch (Exception ex) { .. }
- }
- protected abstract string GetEntitySetName(AdventureWorksObjectContext context);
- public virtual bool Update(T entity)
- {
- if (entity == null)
- throw new ArgumentNullException("entity");
- var ctx = CreateContext();
- entity.EntityKey = ctx.CreateEntityKey(this.GetFullEntitySetName(ctx),
- entity);
- try
- {
- T oldEntity = (T)ctx.GetObjectByKey(entity.EntityKey);
- if (oldEntity == null) return false;
- ctx.ApplyCurrentValues(this.GetFullEntitySetName(ctx), entity);
- ctx.SaveChanges();
- return true;
- }
- catch (Exception ex) { .. }
- }
- }
上述代碼中,我們的BaseRepository類使用ObjectContext類(需要使用CreateContext方法創(chuàng)建每一個請求)和AddObject方法實(shí)現(xiàn)添加新的對象,而通過使用ObjectContext類和AttachTo方法實(shí)現(xiàn)更新現(xiàn)有的對象。對于創(chuàng)建對象而言,我們需要知道要更新哪種類型的方法。使用我們的助理GetFullEntitySetName方法可以很好地處理這個問題。這個方法能夠返回要添加的標(biāo)識實(shí)體的對象(一個如DotNetSamplesObjectContext.Customers的值)的標(biāo)識。
對于更新一個對象而言,我們遇到了與上下文有關(guān)的問題。每個從數(shù)據(jù)庫中查詢的對象都使用ObjectStateManager類中的ObjectContext成員進(jìn)行跟蹤。MVC綁定過程實(shí)際上已經(jīng)構(gòu)建了它自己的對象副本,并通過反射把這些值注入到此對象中。這意味著我們有一個新的對象,而不是附加到ObjectContext上的對象。
這不是一個大問題,我們首先需要查詢舊記錄。這將為我們的實(shí)體生成一個ObjectStateEntry,并且我們可以成功地執(zhí)行更新(因?yàn)樗枰琅f記錄是什么)。該實(shí)體還需要使用一個EntityKey實(shí)體,提供適當(dāng)?shù)闹麈I信息(記住,EntityKey是確定出已存在的實(shí)體的唯一的方式)。
***,調(diào)用ApplyCurrentValues能夠把MVC框架所創(chuàng)建的新的實(shí)體值應(yīng)用到舊實(shí)體上。在這里,我們?nèi)匀恍枰褂脤?shí)體集的名稱來唯一標(biāo)識它。
三、元數(shù)據(jù)
在上面代碼中,我們看到了實(shí)體集名稱的使用方法,用來確定ADO.NET實(shí)體框架中的實(shí)體的類型。例如,它可以用于描述Products表和Product實(shí)體之間的一個映射。還例如,對于我們的產(chǎn)品信息庫來說,它可以執(zhí)行下列操作以獲取實(shí)體集。
清單2—返回產(chǎn)品實(shí)體集名稱
- protected override Expression
> GetDefaultSortingExpression() - {
- return j => j.ProductID;
- }
- protected override string GetEntitySetName(AdventureWorksObjectContext context)
- {
- return context.Products.EntitySet.Name;
- }
我們很快將會看到GetDefaultSortingExpression的使用。請注意,這里的GetFullEntitySetName方法把對象的上下文名稱追加到實(shí)體集名稱的后面,以取得添加,更新等操作對應(yīng)對象的正確名稱?!?/p>
四、數(shù)據(jù)檢索
一般地,我們還可以執(zhí)行一些讀取操作,如下所示。
清單3—從數(shù)據(jù)庫讀取數(shù)據(jù)
- protected virtual string GetKeyProperty()
- {
- PropertyInfo[] properties = typeof(T).GetProperties();
- foreach (PropertyInfo property in properties)
- {
- EdmScalarPropertyAttribute attrib = property.GetCustomAttributes
- (typeof(EdmScalarPropertyAttribute), false).FirstOrDefault() as EdmScalarPropertyAttribute;
- if (attrib != null && attrib.EntityKeyProperty)
- return property.Name;
- }
- return null;
- }
- public virtual T Get(int key)
- {
- string prop = this.GetKeyProperty();
- if (string.IsNullOrEmpty(prop))
- return null;
- var ctx = CreateContext();
- return (T)ctx.GetObjectByKey(new EntityKey(this.GetFullEntitySetName(ctx),
- prop, key));
- }
- public virtual IQueryable
GetAll(int pageIndex, int pageSize) - {
- var ctx = CreateContext();
- return ctx.CreateObjectSet
(this.GetFullEntitySetName(ctx)).OrderBy(this.GetDefaultSortingExpression()) - .Skip(pageIndex * pageSize).Take(pageSize);
- }
默認(rèn)設(shè)計器生成的每個實(shí)體類都將把一組屬性添加到它對應(yīng)的每一個字段屬性上。其中,EdmScalarPropertyAttribute擁有EntityKeyProperty設(shè)置,被設(shè)置為true,對應(yīng)于實(shí)體的鍵字段。這就提供了一種靈活的方式來確定主鍵列而不需要使用一個lambda表達(dá)式手動指定。
跟蹤分析到ObjectContext方法內(nèi)部,你會發(fā)現(xiàn)通過使用實(shí)體集名稱構(gòu)造一個對象集合可以取得一個數(shù)據(jù)實(shí)體的所有結(jié)果。對象集可以使用LINQ擴(kuò)展方法來按索引頁和大小加以過濾,例如只取得一個包含20個對象的結(jié)果集。不幸的是,調(diào)用Skip和Take方法需要先對對象進(jìn)行排序。同樣,你需要使用一個自定義Lambda表達(dá)式來執(zhí)行這個排序操作。
GetObjectByKey方法實(shí)際上使用它的鍵從它的數(shù)據(jù)庫中檢索對象。我們可以利用我們的新的GetKeyProperty反射方法來獲取主鍵屬性的名稱。正如你所看到的,我們不能直接使用這個鍵而需要使用一個EntityKey對象來檢索它。
五、最終實(shí)現(xiàn)
我可以利用一個類似下面的信息庫,并且已經(jīng)在基類中實(shí)現(xiàn)了Create、Delete、Update、Get和GetAll方法。我們只需要關(guān)心的是,實(shí)現(xiàn)其他的查詢操作。
清單4—最終版本的數(shù)據(jù)倉庫類(其他其他前面已列舉的內(nèi)容)
- public class ProductsRepository : BaseRepository
- {
- protected override Expression
> GetDefaultSortingExpression() - {
- return j => j.ProductID;
- }
- protected override string GetEntitySetName(DA.DotNetSamplesObjectContext context)
- {
- return context.Products.EntitySet.Name;
- }
- }
在大多數(shù)情況下,代碼生成將是***的選擇,有助于減少重復(fù)代碼,但是,實(shí)體框架做了大量的內(nèi)部基礎(chǔ)工作(實(shí)現(xiàn)基礎(chǔ)代碼的自動生成)來實(shí)現(xiàn)這些特征支持而無需我們編寫任何代碼。
六、結(jié)論
ADO.NET實(shí)體框架提供了大量基礎(chǔ)功能,節(jié)省了開發(fā)人員大量的代碼編寫時間。在本文中,我們討論了ObjectContext類提供給我們的許多方法,其中包括從后端數(shù)據(jù)庫獲取和存入數(shù)據(jù),等等。
***,我們有理由相信,ADO.NET實(shí)體框架必將在ASP.NET MVC框架應(yīng)用程序開發(fā)的數(shù)據(jù)管理模型開發(fā)中發(fā)揮越來越大的作用。
【編輯推薦】
- Linq匿名類型簡單概述
- Linq隨機(jī)讀取數(shù)據(jù)淺析
- Linq Lambda表達(dá)式全面分析
- Linq擴(kuò)展方法簡單分析
- 初探Linq局部變量類型
標(biāo)題名稱:詳解ASP.NET MVC 2中的新ADO.NET實(shí)體框架
瀏覽地址:http://m.5511xx.com/article/cdoshod.html


咨詢
建站咨詢
