实体框架Entity Framework 是 ADO.NET 中的一组支持开发面向数据的软件应用程序的技术。是微软的一个ORM框架。
ORM是面向对象的对象模型(实体)和关系型数据(表)的数据结构之间的相互转换狭义上,ORM可以被认为是,基于关系型数据库的数据存储,实现一个虚拟的面向对象的数据访问接口。ORM就是将我们把实体的变化映射成数据库表的变化。其实就是拿到对象模型的变化,通过sql脚本的形式对数据库表进行变化。O代码Obeject R 就是表,Mapping代表映射关系。
下面,我们通过一个简单的Demo来观察理解EF框架的功能。
第一步:创建一个控制台应用程序,创建的步骤在这里就省略了。
第二步:右击刚建立好的项目,选择添加新建项目,添加一个实体对象模型.
在实体数据模型向导中模型内容选择从数据库生成。
点击下一步,选择数据源,单击确定。
单击确定按钮,我们可以发现在资源管理器上,我们所选择的数据库和表的信息全部映射了过来。在我们所创建的项目下面,双击.edmx文件,
所有表的信息也都映射了过来
在打开它的cs文件的时候,我们可以醒目的看到“上下文”这三个非常有意思字。上下文就是ObjectContext,它封装了.NET.Framework和数
据库之间的连接。用作创建,读取,更新和删除操作的网关,Entity Framework利用了抽象化数据结构的方式,将每个数据库的对象转换成
相应的应用程序的对象,数据字段都转换为了属性,关系转换为了结合属性,将数据库的E/R模型完全转换成了对象模型。
下面我们来通过EF框架来实现其与数据库之间的沟通吧。我们来为ClassInfo这个表进行一些简单的增删改查。
在ClassInfo中添加一条记录:
1 ExamEntities dbContext = new ExamEntities(); 2 ClassInfo classinfo = new ClassInfo(); 3 #region 添加 4 classinfo.AddTime = DateTime.Now; 5 classinfo.ClassName = "实验小学2班"; 6 classinfo.DelFlag = false; 7 classinfo.Remark = "实验小学是我们学校平均成绩最好的一个班"; 8 dbContext.ClassInfo.Attach(classinfo); 9 dbContext.ObjectStateManager.ChangeObjectState(classinfo, EntityState.Added); 10 dbContext.SaveChanges(); 11 #endregion
方便的是,我们可以通过vs对数据库进行操作,在服务器资源管理器中找到我们操作的表格,右击新建查询,我们就可以查询到数据库中数据的变化,接着让我们来验证一下数据库中的变化吧
我们很惊奇的发现它确实在数据库中发生了变化,其实在内部,有一个执行sql语句的驱动程序已经将其转换成sql语句了,它的实现也是基于ADO.NET之上的。所以我们不必在乎它的内部处理过程,只管放心的使用就Ok了。
更新和删除操作用这种方式也很简单,在这里我就不一一的做介绍了,这里有一个简单的Demo,大家看一下就可以一目了然。
1 ExamEntities dbContext = new ExamEntities();
2 ClassInfo classinfo = new ClassInfo();
3 #region 删除 2 classinfo.ClassId = 16; 3 dbContext.ClassInfo.Attach(classinfo); 4 dbContext.ObjectStateManager.ChangeObjectState(classinfo,EntityState.Deleted); 5 dbContext.SaveChanges(); 6 #endregion 7 #region 更新 8 classinfo.ClassId = 2; 9 classinfo.ClassName = "实验小学3班"; 10 classinfo.DelFlag = false; 11 classinfo.AddTime = DateTime.Now; 12 classinfo.Remark = "你好"; 13 dbContext.ClassInfo.Attach(classinfo); 14 dbContext.ObjectStateManager.ChangeObjectState(classinfo, EntityState.Modified); 15 dbContext.SaveChanges(); 16 #endregion
下面是通过使用EF框架对数据库中内容进行查询并返回数据的程序:
1 #region 查询 2 //当数据量非常小的时候可以使用此种方法查询,当数据量非常大的时候,避免使用此种方法,此种方法有可能会毁掉系统内存 3 //所以我们一般不用这种方法,而是使用下列方法 4 foreach (var classinformation in dbContext.ClassInfo) 5 { 6 if (classinfo.ClassId >= 10) 7 { 8 Console.WriteLine(classinformation.ClassName + classinformation.ClassId); 9 } 10 } 11 //EF对数据进行过滤(使用Linq表达式) 12 //使用此种方式,会相对安全,使用Lambda表达式找出ClassId大于10的数据,并将它们的ClassId,ClassName属性输出 13 //在select后,用匿名类表示 14 //在数据库中,查询语句的执行顺序为from,where,select 15 //in 就相当于foreach循环和foreach(var c in dbContext.ClassInfo)是一样的 16 // 微软并没有将数据库中的所有的数据都加载到内存中再进行过滤,而是将link表达式转换成了响应的sql脚本。(是一种高效的sql脚本) 17 //Linq表达式返回来的类型是IQueryable类型的,这里我们使用的是var类型推断,在程序进行编译期间,确定它的类型 18 19 var data = from c in dbContext.ClassInfo where c.ClassId >= 10 select new{classId=c.ClassId,className=c.ClassName}; 20 foreach (var classinformation in data) 21 { 22 Console.WriteLine(classinformation.classId+classinformation.className); 23 } 24 #endregion 25 #region 当表进行连接的时候进行部分列的查询语句 26 Console.WriteLine("-----------------------------------------------------------------------------------"); 27 var data1 = from c in dbContext.ClassInfo 28 join s in dbContext.StudentInfo on c.ClassId equals s.ClassId 29 select new {cclassId=c.ClassId,sclassId=s.ClassId,cclassName=c.ClassName,sclassName=s.NickName}; 30 foreach (var joininfo in data1) 31 { 32 Console.WriteLine(joininfo.cclassId+joininfo.cclassName+joininfo.sclassId+joininfo.sclassName); 33 } 34 #endregion 35 36 #region 查询部分列 37 38 Console.WriteLine("-----------------------------------------------------------------------------"); 39 40 var data2 = from c in dbContext.ClassInfo 41 where c.ClassId==2 && c.ClassName.Contains("小学")//在编写代码的时候不要忘记了where 42 select new {c.ClassId,c.ClassName}; 43 foreach (var classInformation in data2) 44 { 45 Console.WriteLine(classInformation.ClassId+classInformation.ClassName); 46 } 47 #endregion 48 #region 对表内容进行分组之后进行查询 49 Console.WriteLine("----------------------------------------------------------------------------"); 50 //进行分组时,Linq表达式中g代表分组,Key指的是根据什么进行分组,Count指分组之后对应的数据的个数 51 var data3 = from c in dbContext.ClassInfo group c by c.ClassId into g select new{g.Key,Count=g.Count()} ;//key指的是ClassId,Count()指的是组的个数 52 foreach (var classinformation in data3) 53 { 54 Console.WriteLine(classinformation.Key+":"+classinformation.Count); 55 } 56 #endregion 57 58 59 //Linq表达式进行查询的部分用Lambda表达式也能完成操作 60 //Lambda表达式进行查询 61 Console.WriteLine("--------------------------------------"); 62 //lambda表达式进行简单查询 63 var lamdata = dbContext.ClassInfo.Where(c => c.ClassId == 2 && c.ClassName.Contains("小学")); 64 List<IQueryable> list=new List<IQueryable>(); 65 //lambda表达式进行分组,并得出每组的个数 66 var lamdata3 = dbContext.ClassInfo.GroupBy(c => c.ClassId); 67 foreach (var classinformation in lamdata3) 68 { 69 Console.WriteLine(classinformation.Key+":"+classinformation.Count()); 70 } 71 72 Console.ReadKey(); 73 }
由此可见,EF框架确实具有很强大的功能,但是它在生成sql脚本的时候也是非常损耗性能的,这也是它的一种缺陷。但是在开发起来确实也是很方便的。
接下来,我们就以EF框架原理图来结束这篇小博文吧