Entity Framework将概念模型中定义的实体和关系映射到数据源,利用实体框架可以将数据源返回的数据具体化为对象;跟踪对象所做的更改;并发处理;将对象更改传播到数据源等。今天我们就一起讨论如何利用Entity Framework进行查询、插入、更新和删除数据。

查询

我们将使用AdventureWorks数据库来进行今天的所有演示,因此开始之前请准备好相应的数据库。在EF中进行查询应该说是相当简单,只需要定义一个类继承于“DbContext”,然后定义对应的“DbSet”集合属性即可。例如下面的“AdventureWorksContext”类:

using System.Data.Entity; using System.Data.Entity.Infrastructure; using EFPowerTools.Models.Mapping; namespace EFPowerTools.Models { public partial class AdventureWorksContext : DbContext { static AdventureWorksContext() { Database.SetInitializer<AdventureWorksContext>(null); } public AdventureWorksContext() : base("Name=AdventureWorksContext") { } public DbSet<Employee> Employees { get; set; } public DbSet<Person> People { get; set; } } }

一个数据库上下文的生命周期随着该对象的创建而开始,随着对象的释放(或GC回收)而结束,因此建议在开发过程中使用“Using”编码方式,这样就可以免去手动释放对象的操作。如下面的代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var persons = db.People.Where(p => p.LastName == "Stevens").OrderBy(p=>p.FirstName); foreach(var p in persons) { Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName); } } } } } 

另外对于数据库连接的管理在EF中是透明的,我们一般不需要手动进行处理,当查询一个对象时打开连接当处理完查询的结果集之后会自动关闭连接。

在EF的Code First模式中有三种常用的数据查询方式(Model First和Database First中还有其他方式如:使用Entity SQL,但这不是我们今天的重点):Linq To Entity表达式查询、基于方法的查询、原生SQL查询。

Linq To Entity表达式查询

查询表达式是C#3.0新增的功能,它是由一组类似于T-SQL或XQuery声明性语句组成,CLR并不能直接读取这种查询表达式而是在编译时转换为对应的方法调用。如下面的例子:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var persons = from p in db.People where p.LastName == "Stevens" orderby p.FirstName select p; foreach (var p in persons) { Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName); } } } } } 

基于方法的查询

基于方法的查询事实上是一组对象的扩展方法,同Linq查询不同的是这些方法可以直接被CLR识别并运行。

例如上面的方法我们可以转换为如下代码,他们的效果是一样的,返回的都是“IQueryable”对象:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var persons = db.People.Where(p => p.LastName == "Stevens").OrderBy(p => p.FirstName); foreach (var p in persons) { Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName); } } } } } 

原生SQL查询

EF还支持原生SQL查询(注意与Entity SQL区别),例如:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; using System.Data.Objects; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var persons = db.People.SqlQuery("SELECT * FROM Person.Person WHERE LastName='Stevens'"); foreach (var p in persons) { Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName); } } } } } 

不仅如此,EF还支持非实体类型的查询:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; using System.Data.Objects; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var persons = db.Database.SqlQuery<string>("SELECT FirstName FROM Person.Person WHERE LastName='Stevens'").ToList(); foreach (var p in persons) { Console.WriteLine("FirstName:{0}", p); } } } } } 

当然也支持无返回值的SQL命令:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; using System.Data.Objects; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { db.Database.ExecuteSqlCommand("UPDATE Person.Person SET NameStyle=1 WHERE BusinessEntityID='1813'"); } } } } 

增加

在EF中添加操作一般有两种方式:一是直接创建对象,然后调用“DbSet”的”Add()”方法进行添加;二是调用数据库上下文的”Entry()”方法并设置对应的状态。无论使用哪种方式最终一定要调用“SaveChange()”进行提交。如:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var stephen = new Person { BusinessEntityID=20778, PersonType="EM", NameStyle=false, Title="Architec", FirstName="Stephen", LastName="Chow", EmailPromotion=1, rowguid = Guid.NewGuid(), ModifiedDate = DateTime.Now }; db.People.Add(stephen); var jeffrey = new Person { BusinessEntityID = 20779, PersonType = "EM", NameStyle = false, Title = "Engineer", FirstName = "Jeffrey", LastName = "Lee", EmailPromotion = 0, rowguid=Guid.NewGuid(), ModifiedDate=DateTime.Now }; db.Entry(jeffrey).State = EntityState.Added; db.SaveChanges(); } } } } 

效果如图:

此外,在含有导航属性时,将一个对象赋值给另一个对象的导航属性也能达到添加的效果(当导航属性为”DbSet“集合时通过调用导航属性的“Add()“方法也同样可以达到添加效果),例如在”Person.Person”中我们上面添加了两条记录,但对于“Person”类的导航属性“EmailAddress”和“Password”在对应的“EmailAddress”表和“Password”表中并没有添加对应的记录,此时我们就可以通过下面的方式来增加:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var password = new Password { BusinessEntityID=20778, PasswordHash = "ZEgQH9qZIPiLgyBHYw/dD1FJQNpdQyIAa+BFfKX5/jg=", PasswordSalt = "7iy/umc=", rowguid=Guid.NewGuid(), ModifiedDate=DateTime.Now }; var email = new EmailAddress { BusinessEntityID = 20778, EmailAddress1 = "StephenChow@outlook.com", rowguid = Guid.NewGuid(), ModifiedDate = DateTime.Now }; var person = db.People.Find(20778); person.Password = password; person.EmailAddresses.Add(email); db.SaveChanges(); } } } } 

此时查看将可以看到“EmailAddress”表中确实增加了一条记录(“Password”表同样也是如此):

状态跟踪

在这里我们需要强调一点那就是状态跟踪,对于上面的操作如果我们调用“Attach()”方法对实体进行跟踪或者设置实体的状态那么数据将不会保存到数据库:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var stephen = new Person { BusinessEntityID = 20778, PersonType = "EM", NameStyle = false, Title = "Architec", FirstName = "Stephen", LastName = "Chow", EmailPromotion = 1, rowguid = Guid.NewGuid(), ModifiedDate = DateTime.Now }; db.People.Add(stephen); db.People.Attach(stephen); //db.Entry(stephen).State = EntityState.Unchanged;//同上面db.People.Attach(stephen);作用一样 db.SaveChanges(); } } } } 

使用”Attach()”方法进行实体跟踪时会设置实体的状态为“Unchanged”此时实体处于未修改状态,当执行“SaveChange()”方法时EF不会执行修改操作。相反如果此时设置实体状态为“Modified”则EF执行更新操作。那么既然EF的数据修改操作(增加、更新、删除)是根据实体状态而进行的,那么为什么之前我们的增加操作能正常进行而不用手动修改其状态呢?原因是EF会自动发现状态改变,在调用下面的方法时状态发现是自动的:

· DbSet.Find

· DbSet.Local

· DbSet.Remove

· DbSet.Add

· DbSet.Attach

· DbContext.SaveChanges

· DbContext.GetValidationErrors

· DbContext.Entry

· DbChangeTracker.Entries

当然,并不是所有的时候我们都需要EF自动发现状态改变,设置 “DbContext.Configuration.AutoDetectChangesEnabled”属性为“false”可以禁用自动发现功能。

注意:在EF对数据操作时有时会抛出:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
此时可以使用try{} catch(DbEntityValidationException ex){} 对异常进行捕获,将鼠标放到ex上并逐级查看ex的信息进行解决。

删除

下面看一下EF的删除操作:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; using System.Data.Objects; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var mail = db.EmailAddresses.Where(m => m.EmailAddressID == 19977).FirstOrDefault(); db.EmailAddresses.Remove(mail); db.SaveChanges(); } } } } 

当然有了上面状态跟踪的讨论相信大家也可以想到如下删除方法:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; using System.Data.Objects; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var mail = db.EmailAddresses.Where(m => m.EmailAddressID == 19976).FirstOrDefault(); db.Entry(mail).State = EntityState.Deleted; db.SaveChanges(); } } } } 

修改

修改数据很简单,直接修改对应的属性即可:

using System; using System.Collections.Generic; using System.Data; using System.Data.Entity.Validation; using System.Linq; using System.Text; using System.Threading.Tasks; using EFPowerTools.Models; using System.Data.Objects; namespace EFPowerTools { class Program { static void Main(string[] args) { using (var db = new AdventureWorksContext()) { var person = db.People.Where(p => p.LastName == "Stevens").OrderBy(p=>p.BusinessEntityID).FirstOrDefault(); person.NameStyle = false; person.EmailAddresses.First().EmailAddress1 = "KenshinCui@outlook.com"; db.SaveChanges(); } } } } 

需要说明的是,EF在执行修改操作前会检查哪些属性发生了变化,并且只会修改发生变化的字段。

今天的内容就先到这里了,从前面的EF5.0概览到现在的数据操作,关于EF5.0基础的入门内容已经说完了,更多内容敬请关注后面的文章。

- (void)configDelegate {
	__weak typeof(self) weakSelf = self;
	[self.delegate setSelectRowAtIndexPathBlock:^(id cell, NSIndexPath *indexPath) {
	  TMPremiereBrand *premiereBrand = (TMPremiereBrand *)weakSelf.data[indexPath.row];
	  TMSpecialTopicController *specialTopicController = [[TMSpecialTopicController alloc] init];
	  specialTopicController.premiereBrandID = premiereBrand.ID;
	  [weakSelf.navigationController pushViewController:specialTopicController animated:YES];
	}];
}
 

Entity Framework 5.0系列之数据操作的更多相关文章

  1. Entity Framework 5.0系列之Code First数据库迁移

    我们知道无论是"Database First"还是"Model First"当模型发生改变了都可以通过Visual Studio设计视图进行更新,那么对于Cod ...

  2. Entity Framework 5.0系列之EF概览

    概述 在开发面向数据的软件时我们常常为了解决业务问题实体.关系和逻辑构建模型而费尽心机,ORM的产生为我们提供了一种优雅的解决方案.ADO.NET Entity Framework是.NET开发中一种 ...

  3. Entity Framework 5.0系列之自动生成Code First代码

    在前面的文章中我们提到Entity Framework的"Code First"模式也同样可以基于现有数据库进行开发.今天就让我们一起看一下使用Entity Framework P ...

  4. 【转】Entity Framework 5.0系列之自动生成Code First代码

    在前面的文章中我们提到Entity Framework的“Code First”模式也同样可以基于现有数据库进行开发.今天就让我们一起看一下使用Entity Framework Power Tools ...

  5. Entity Framework 5.0系列之约定配置

    Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来复杂,大家也都试图将软件设计的越来越灵活,很多内容我们都希望是可配置的, ...

  6. 【转】Entity Framework 5.0系列之约定配置

    Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来复杂,大家也都试图将软件设计的越来越灵活,很多内容我们都希望是可配置的, ...

  7. 在Entity Framework 4.0中使用 Repository 和 Unit of Work 模式

    [原文地址]Using Repository and Unit of Work patterns with Entity Framework 4.0 [原文发表日期] 16 June 09 04:08 ...

  8. 【转】Entity Framework技术导游系列开篇与热身

    转自:http://blog.csdn.net/bitfan/article/details/12779517 Entity Framework走马观花 之 把握全局 ================ ...

  9. 开发 ASP.NET vNext 续篇:云优化的概念、Entity Framework 7.0、简单吞吐量压力测试

    继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之后, 关于云优化和版本控制: 我本想做一下MAC和LINUX的self-ho ...

随机推荐

  1. visual studio 编辑窗口 设置固定选项卡 使窗口选项卡多行显示

    工具>选项> 确定后 如图就可以多行显示了.

  2. enable feature AJAX of MOSS2007

    As default, the feature AJAX of MOSS2007 is disabled, so the site web configuration file should be m ...

  3. LInux配置jdk(mac和windows)

    我的linux使用的是VMware搭建的虚拟环境,用的是CENTOS6.5 一.准备工作: 1.确定系统安装的是成功的. 2.系统没有其他的问题 3.确定没有安装过其他版本的jdk,两个jdk会反冲 ...

  4. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  5. java中常用的工具类(一)

    我们java程序员在开发项目的是常常会用到一些工具类.今天我汇总了一下java中常用的工具方法.大家可以在项目中使用.可以收藏!加入IT江湖官方群:383126909 我们一起成长 一.String工 ...

  6. angularJS ng-grid 配置

    以下是按我的需求修改的 简单的demo  可以自己扩展 HTML: <!DOCTYPE html> <html class="no-js" ng-app=&quo ...

  7. Android 利用SurfaceView进行图形绘制

    SurfaceView使用介绍 SurfaceView是View的一个特殊子类,它的目的是另外提供一个线程进行绘制操作. 要使用SurfaceView进行绘制,步骤如下: 1.用SurfaceView ...

  8. Sum All Odd Fibonacci Numbers

    function sumFibs(num) { //return num; var arr = [1,1]; var add = 2; while(true){ var item = arr[0] + ...

  9. poi 读取 excel(.xlsx) 2007及以上版本

    1.注意的一点是sh.getLastRowNum(),比实际的行数少一行 涉及到的包:

  10. javascript笔记4-函数表达式

    一般形式的创建函数,在执行代码之前会先读取函数声明,所以可以把函数声明写在函数调用的下面: sayHi(); function sayHi(){ alert("Hi!"); } 使 ...