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语句的转换。可惜DbContext不支持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!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 1. 什么是ORM ORM的全称是Object Relational Mapping,即对象关系映射。它的实现思...
    codeice阅读 1,083评论 0 1
  • 很多应用程序都需要与数据库交互。数据库是一个数据仓库,与文本文件和 XML 文件极其相似。可以想见,使用文件来存储...
    CarlDonitz阅读 279评论 0 1
  • 自从学习.NET以来,优雅的编程风格,极度简单的可扩展性,足够强大开发工具,极小的学习曲线,让我对这个平台产生了浓...
    taony阅读 1,406评论 0 42
  • “所有不经过导演亲口认同的影评都是过分解读的阅读理解。” —— 沃.兹吉硕德。 在我心里,科幻/魔幻类(以下统称科...
    正在修炼的西瓜君阅读 220评论 0 0
  • 耳匣的你 轻诉胸中那一抹红 浇湿了我的巾帕 打乱了我的盘发 吹响了我的诗句 伪装了你的上卦 左手边 你看过那一场大...
    臾止阅读 250评论 0 1