1. ORM框架之EntityFramework介紹

目錄

1. 自我介紹

傳說中的程序猿

大家好!我是高堂。
作為一位偽前端程序猿,我給大家介紹一下微軟的自家的 ORM框架。

ADO.NET Entity Framework 以下簡稱 EF

2. 什么是EF?

ADO.NET Entity Framework

微軟用來替代ADO.NET的一套 ORM 框架.

以 Entity Data Model (EDM) 為主,將數據邏輯層切分為三塊,分別為 Conceptual Schema, Mapping Schema 與 Storage Schema 三層,其上還有 Entity Client,Object Context 以及 LINQ 可以使用。

EF框架 發展歷史:

版本 支持.NET 發布情況 備注
EntityFramework 3.5 2.0+ 包含于.NET 3.5中 支持EDMX生成,通過擴展可支持POCO類的生成
Entity Framework 4.0 4.0+ 包含于.NET 4.0中
Entity Framework 4.X 可通過NuGet獲取 支持Database First、Model First、Code First三種生成模式
Entity Framework 4.5 4.5+ 集成于.NET 4.5中
Entity Framework 5.X 4.5+ 可通過NuGet獲取 支持枚舉字段,性能有較大提升,支持.NET 4.0的版本 為Entity Framework 4.4
EnittyFramework 6.X 4.0+ 可通過NuGet獲取
EnittyFramework 7.X 4.6+ 可通過NuGet獲取 現在更名為 EntityFramework Core,結合Net Core使用,多用于跨平臺

ADO.NET: 一般使用SQLHelper直接來操作數據庫。

3. 什么是 ORM ?

O/R Mapping 關系圖

ORM => 對象關系映射(英語:Object Relational Mapping)對于O/R,即 Object(對象)和 Relational(關系型數據),表示必須同時使用面向對象和關系型數據進行開發。

ORM框架 用途 => 為了解決 軟件項目數據庫 打交道的中間層。

為什么需要 ORM框架 呢?

因為軟件項目 是面向對象為基本原則; 而 數據庫 則是從數據理論發展而來的;兩套理論存在明顯的的差異。

ORM框架 到底是什么呢? 我還是不太清楚!!!
ORM 其實有三大核心原則:

  • 簡單:以最基本的形式建模數據。
  • 傳達性:數據庫結構被任何人都能理解的語義化文檔。
  • 精準性:基于數據模型創建正確標準了的結構。

簡單的說 ORM 相關于中繼數據。具體到產品上,例如 ADO.NET Entity Framework 實體類的屬性,就算是一種中繼數據。在后面我會給大家詳細介紹 EF框架。

4. EF 與 ADO.NET 有關系嗎?

EF首先生成sql,再調用ado.net訪問數據庫,最后使結果對象具體化.

5. EF 與 ADO.NET 的對比——EF優勢何在?

  • 業務邏輯數據存取邏輯分離開來;
  • 新增操作 EF:一次連接,執行多條sql;SqlHelper里使用一般寫法,連接又無法釋放,用using,會造成多次連接重置;
  • 更新操作 EF自動優化,只update set 有變化的字段,EF也可以很方便地只更新實體的指定屬性,產生的sql語句里的set后的字段會更少;
  • 智能提示 用linq, lamda表達式 有智能提示,寫錯了編譯不過;寫sql語句字符串,調sqlhelper,sql語句寫錯一樣編譯通過;
  • 安全 省去了防止sql注入的麻煩;
  • 數據庫變更 使用EF,切換較方便;
  • 效率 使用EF要比使用Ado.net開發效率高;
  • 可讀性 代碼的可讀性更高.

6. 世面上有哪一些 ORM 產品呢?

  • NHibernate框架 來源于 Java 的 Hibernate 框架,采用XML文件配置的方式。
  • Castle ActiveRecord 框架 是 Castle 中的一個子項目,底層封裝了 NHibernate,改用 Attribute 來代替配置文件,這樣就不用像 NHibernate 那樣配置復雜的文件了。
  • iBATIS.NET 框架 分為 DataMapper 和DataAccess兩部分,DataMapper是這個框架的核心, DataMapper使用XML文件實現從實體到 SQL statements 的映射,學習起來非常簡單,使用DataMapper 以后,我們可以自由的使用 SQL 語句或存儲過程; DataMapper 允許我們通過一個簡單的接口來操作數據,而不必了解底層實現的細節。
  • ADO.NET Entity Framework框架 是NET開發人員的福音,微軟的東西,簡單,容易上手等特點。和 Visual Studio SQLServer等軟件無縫集成,作為一位 NET 陣營的 童鞋們,你們懂的!

7. EF的開發模式

EF的開發模式

從4.1版本開始,EF開始支持三種開發模式

  • Database First模式

我們稱之為“數據庫優先”,前提是你的應用已經有相應的數據庫,你可以使用EF設計工具根據數據庫生成數據數據類,你可以使用Visual Studio模型設計器修改這些模型之間對應關系。

  • Model First模式

我們稱之為“模型優先”,這里的模型指的是“ADO.NET Entity Framework Data Model”,此時你的應用并沒有設計相關數據庫,在Visual Studio中我們通過設計對于的數據模型來生成數據庫和數據類。

  • Code First模式

我們稱之為“代碼優先”模式,是從EF4.1開始新建加入的功能。使用Code First模式進行EF開發時開發人員只需要編寫對應的數據類(其實就是領域模型的實現過程),然后自動生成數據庫。這樣設計的好處在于我們可以針對概念模型進行所有數據操作而不必關系數據的存儲關系,使我們可以更加自然的采用面向對象的方式進行面向數據的應用程序開發。

8. Entity Framework 增刪改查

8.1 增加對象

DbEntity db = new DbEntity();
//創建對象實體,注意,這里需要對所有屬性進行賦值(除了自動增長主鍵外),如果不賦值,則會數據庫中會被設置為NULL(注意是否可空)
var user = new User
            {
                Name = "bomo",
                Age = 21,
                Gender = "male"
            };
db.User.Add(user);
db.SaveChanges();

8.2 刪除對象,刪除只需要對象的主鍵

DbEntity db = new DbEntity();
//刪除只需要主鍵,這里刪除主鍵為5的行
var user = new User {Id = 5};
//將實體附加到對象管理器中
db.User.Attach(user);
//方法一:
db.User.Remove(user);
//方法二:把當前實體的狀態改為刪除
//db.Entry(user).State = EntityState.Deleted;
db.SaveChanges();

8.3 修改對象

方法一:

DbEntity db = new DbEntity();
//修改需要對主鍵賦值,注意:這里需要對所有字段賦值,沒有賦值的字段會用NULL更新到數據庫
var user = new User
    {
        Id = 5,
        Name = "bomo",
        Age = 21,
        Gender = "male"
    };
//將實體附加到對象管理器中
db.User.Attach(user);
//把當前實體的狀態改為Modified
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();

方法二:方法一中每次都需要對所有字段進行修改,效率低,而且麻煩,下面介紹修改部分字段

DbEntity db = new DbEntity();
//修改需要對主鍵賦值,注意:這里需要對所有字段賦值,沒有賦值的字段會用NULL更新到數據庫
var user = new User
    {
        Id = 5,
        Name = "bomo",
        Age = 21
    };
//將實體附加到對象管理器中
db.User.Attach(user);

//獲取到user的狀態實體,可以修改其狀態
var setEntry = ((IObjectContextAdapter) db).ObjectContext.ObjectStateManager.GetObjectStateEntry(user);
//只修改實體的Name屬性和Age屬性
setEntry.SetModifiedProperty("Name");
setEntry.SetModifiedProperty("Age");

db.SaveChanges();

8.4 使用事務:使用事務很簡單,只要把需要的操作放在 TransactionScope 中,最后提交.

DbEntity db = new DbEntity();
using (var scope = new TransactionScope())
{
    //執行多個操作
    var user1 = new User
    {
        Name = "bomo",
        Age = 21,
        Gender = "male"
    };
    db.User.Add(user1);
    db.SaveChanges();
    
    var user2 = new User
    {
        Name = "toroto",
        Age = 20,
        Gender = "female"
    };
    db.User.Add(user2);
    db.SaveChanges();

    //提交事務
    scope.Complete();
}

8.5 查詢:查詢通過LinQ查詢.

DbEntity db = new DbEntity(); 
//選擇部分字段 
var user = db.User.Where(u => u.Name == "bomo")
                            .Select(u => new {Id = u.Id, Name = u.Name, Age = u.Age})
                            .FirstOrDefault(); 
//只有調用了FirstOrDefault, First, Single, ToList, ToArray等函數才會執行對數據庫的查詢

9. EF 查詢相關

EF提供的查詢方式有以下幾種

  • 原始SQL查詢
  • LINQ To Entity and Lambda
  • ESQL 與 ObjectQuery
  • ObjectQuery 查詢生成器

9.1 原始SQL查詢

在EF 4.1 新增加的DbContext 除了支持LINQ與Lambda查詢外,新增了支持原始SQL查詢,但是不支持ESQL與ObjectQuery查詢。

DemoDBEntities context = new DemoDBEntities();
DbSet<BlogMaster> set = context.Set<BlogMaster>();
List<BlogMaster> list = set.SqlQuery("select *from BlogMaster where UserId='3'").ToList();
List<BlogMaster> listAll = context.Database.SqlQuery<BlogMaster>("select *from BlogMaster").ToList();

使用原始SQL查詢,既靈活又方便維護,加上DbContext泛型處理,可以將最終的查詢數據集映射成對象集合。而且SQL語句有錯誤時,提醒也比較明確。項目中,大家都會碰到查詢條件經常變動的問題,針對這種情況我們以使用通過定制的查詢模板以SQL拼接的方式解決,而不是修改代碼。

9.2 LINQ To Entity and Lambda

這兩種是比較常用的方式,也是效率比較高的,簡潔方便,但是不靈活,如果條件變了,可能就需要修改代碼。相信做過報表的人都曾為復雜的SQL語句以及SQL語句的執行效率頭痛過,而LINQ和Lambda 方便就在于可以將復雜的SQL拆分出來,在內存中解決這些數據的合并篩選,并且效率要遠高于SQL。我最喜歡的LINQ的一個功能就是他的分組。

DemoDBEntities context = new DemoDBEntities();
DbSet<BlogMaster> set = context.Set<BlogMaster>();
var result = from u in set.ToList()
                        where u.UserID == 3
                        select u;

var resultGroup = from u in set.ToList()
                    group u by u.UserID
                        into g
                        select g;

var list = set.Where(o => o.UserID == 3);
var listGroup = set.GroupBy(o => o.UserID);

不管是哪種方式,LINQ To Entity and Lambda EF 都是支持的。

9.3 ESQL 與 ObjectQuery

首先說明一點,目前DbContext不支持這種方式查詢。ESQL同原始SQL 只是寫法稍為有點區別,但是特點差不多,靈活易于維護。由于可以拼接ESQL,所以這種方式也可以應對查詢條件變化。

DemoDBEntities context = new DemoDBEntities();
//DbSet<BlogMaster> set = context.Set<BlogMaster>();
string queryString = @"SELECT VALUE it FROM DemoDBEntities.BlogMaster as
                    it WHERE it.UserId > @UserId order by it.UserId desc";
ObjectQuery<BlogMaster> query = new ObjectQuery<BlogMaster>(queryString, context);              
// Add parameters to the collection.
query.Parameters.Add(new ObjectParameter("UserId",6));
List<BlogMaster> list = query.ToList();

原始SQL與ESQL 區別在于參數類型的處理,因為原始的SQL你在拼接的條件的時候要對不同的參數值類型處理,例如是where Name='tt' and UserId=6 and Sex=true ,而ESQL則是object傳入,直接實現SQL語句的轉換??上bContext不支持ESQL,所以只能自己去解決SQL條件不同值類型的拼接處理。

9.4 ObjectQuery 查詢生成器

DemoDBEntities context = new DemoDBEntities();
            
ObjectQuery<BlogMaster> query = context.CreateObjectSet<BlogMaster>()
    .Where("it.UserId > @UserId",
    new ObjectParameter("UserId", 6))
    .OrderBy("it.UserId desc");

List<BlogMaster> list = query.ToList();

這種方式基本上有ESQL相同,只是分組,排序,條件過濾都要單獨處理,相比就沒結合ESQL使用靈活了。

以上四種方式各有優缺點,如果是批量做頁面的查詢,每個查詢頁面和條件各不相同,并且查詢條件可能會變動的話,建議使用DbContext的SQL查詢,或者是ESQL結合ObjectQuery,這兩種方式易于通過查詢模板拼接生成SQL語句,但不適合生成復雜的SQL語句。

而LINQ or Lambda 以及ObjectQuery方式,則不適合做一些重復查詢邏輯的工作,而單獨處理一些頁面的查詢或者復雜的報表還是比較靈活的。

10. 結束語

Thanks everyone!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. 什么是ORM ORM的全稱是Object Relational Mapping,即對象關系映射。它的實現思...
    codeice閱讀 1,134評論 0 1
  • 很多應用程序都需要與數據庫交互。數據庫是一個數據倉庫,與文本文件和 XML 文件極其相似。可以想見,使用文件來存儲...
    CarlDonitz閱讀 291評論 0 1
  • 自從學習.NET以來,優雅的編程風格,極度簡單的可擴展性,足夠強大開發工具,極小的學習曲線,讓我對這個平臺產生了濃...
    taony閱讀 1,420評論 0 42
  • “所有不經過導演親口認同的影評都是過分解讀的閱讀理解?!?—— 沃.茲吉碩德。 在我心里,科幻/魔幻類(以下統稱科...
    正在修煉的西瓜君閱讀 240評論 0 0
  • 耳匣的你 輕訴胸中那一抹紅 澆濕了我的巾帕 打亂了我的盤發 吹響了我的詩句 偽裝了你的上卦 左手邊 你看過那一場大...
    臾止閱讀 257評論 0 1