转载原出处:http://www.cnblogs.com/kenshincui/p/3345586.html

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

查询

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

  1. using System.Data.Entity;
  2. using System.Data.Entity.Infrastructure;
  3. using EFPowerTools.Models.Mapping;
  4.  
  5. namespace EFPowerTools.Models
  6. {
  7. public partial class AdventureWorksContext : DbContext
  8. {
  9. static AdventureWorksContext()
  10. {
  11. Database.SetInitializer<AdventureWorksContext>(null);
  12. }
  13.  
  14. public AdventureWorksContext()
  15. : base("Name=AdventureWorksContext")
  16. {
  17. }
  18.  
  19. public DbSet<Employee> Employees { get; set; }
  20. public DbSet<Person> People { get; set; }
  21. }
  22. }

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using EFPowerTools.Models;
  7.  
  8. namespace EFPowerTools
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13.  
  14. {
  15. using (var db = new AdventureWorksContext())
  16. {
  17. var persons = db.People.Where(p => p.LastName == "Stevens").OrderBy(p=>p.FirstName);
  18. foreach(var p in persons)
  19. {
  20. Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName);
  21. }
  22. }
  23. }
  24. }
  25. }

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

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

Linq To Entity表达式查询

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9.  
  10. namespace EFPowerTools
  11. {
  12. class Program
  13. {
  14. static void Main(string[] args)
  15.  
  16. {
  17. using (var db = new AdventureWorksContext())
  18. {
  19. var persons = from p in db.People
  20. where p.LastName == "Stevens"
  21. orderby p.FirstName
  22. select p;
  23.  
  24. foreach (var p in persons)
  25. {
  26. Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName);
  27. }
  28. }
  29. }
  30. }
  31. }

基于方法的查询

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

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9.  
  10. namespace EFPowerTools
  11. {
  12. class Program
  13. {
  14. static void Main(string[] args)
  15.  
  16. {
  17. using (var db = new AdventureWorksContext())
  18. {
  19. var persons = db.People.Where(p => p.LastName == "Stevens").OrderBy(p => p.FirstName);
  20. foreach (var p in persons)
  21. {
  22. Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName);
  23. }
  24. }
  25. }
  26. }
  27. }

原生SQL查询

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9. using System.Data.Objects;
  10.  
  11. namespace EFPowerTools
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16.  
  17. {
  18. using (var db = new AdventureWorksContext())
  19. {
  20. var persons = db.People.SqlQuery("SELECT * FROM Person.Person WHERE LastName='Stevens'");
  21. foreach (var p in persons)
  22. {
  23. Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName);
  24. }
  25. }
  26. }
  27. }
  28. }

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9. using System.Data.Objects;
  10.  
  11. namespace EFPowerTools
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16.  
  17. {
  18. using (var db = new AdventureWorksContext())
  19. {
  20. var persons = db.Database.SqlQuery<string>("SELECT FirstName FROM Person.Person WHERE LastName='Stevens'").ToList();
  21. foreach (var p in persons)
  22. {
  23. Console.WriteLine("FirstName:{0}", p);
  24. }
  25. }
  26. }
  27. }
  28. }

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9. using System.Data.Objects;
  10.  
  11. namespace EFPowerTools
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16.  
  17. {
  18. using (var db = new AdventureWorksContext())
  19. {
  20. db.Database.ExecuteSqlCommand("UPDATE Person.Person SET NameStyle=1 WHERE BusinessEntityID='1813'");
  21. }
  22. }
  23. }
  24. }

增加

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9.  
  10. namespace EFPowerTools
  11. {
  12. class Program
  13. {
  14. static void Main(string[] args)
  15.  
  16. {
  17. using (var db = new AdventureWorksContext())
  18. {
  19. var stephen = new Person
  20. {
  21. BusinessEntityID=20778,
  22. PersonType="EM",
  23. NameStyle=false,
  24. Title="Architec",
  25. FirstName="Stephen",
  26. LastName="Chow",
  27. EmailPromotion=1,
  28. rowguid = Guid.NewGuid(),
  29. ModifiedDate = DateTime.Now
  30. };
  31. db.People.Add(stephen);
  32.  
  33. var jeffrey = new Person
  34. {
  35. BusinessEntityID = 20779,
  36. PersonType = "EM",
  37. NameStyle = false,
  38. Title = "Engineer",
  39. FirstName = "Jeffrey",
  40. LastName = "Lee",
  41. EmailPromotion = 0,
  42. rowguid=Guid.NewGuid(),
  43. ModifiedDate=DateTime.Now
  44. };
  45. db.Entry(jeffrey).State = EntityState.Added;
  46.  
  47. db.SaveChanges();
  48. }
  49. }
  50. }
  51. }

效果如图:

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9.  
  10. namespace EFPowerTools
  11. {
  12. class Program
  13. {
  14. static void Main(string[] args)
  15.  
  16. {
  17. using (var db = new AdventureWorksContext())
  18. {
  19. var password = new Password
  20. {
  21. BusinessEntityID=20778,
  22. PasswordHash = "ZEgQH9qZIPiLgyBHYw/dD1FJQNpdQyIAa+BFfKX5/jg=",
  23. PasswordSalt = "7iy/umc=",
  24. rowguid=Guid.NewGuid(),
  25. ModifiedDate=DateTime.Now
  26. };
  27.  
  28. var email = new EmailAddress
  29. {
  30. BusinessEntityID = 20778,
  31. EmailAddress1 = "StephenChow@outlook.com",
  32. rowguid = Guid.NewGuid(),
  33. ModifiedDate = DateTime.Now
  34. };
  35.  
  36. var person = db.People.Find(20778);
  37. person.Password = password;
  38. person.EmailAddresses.Add(email);
  39.  
  40. db.SaveChanges();
  41. }
  42. }
  43. }
  44. }

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

状态跟踪

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9.  
  10. namespace EFPowerTools
  11. {
  12. class Program
  13. {
  14. static void Main(string[] args)
  15.  
  16. {
  17. using (var db = new AdventureWorksContext())
  18. {
  19. var stephen = new Person
  20. {
  21. BusinessEntityID = 20778,
  22. PersonType = "EM",
  23. NameStyle = false,
  24. Title = "Architec",
  25. FirstName = "Stephen",
  26. LastName = "Chow",
  27. EmailPromotion = 1,
  28. rowguid = Guid.NewGuid(),
  29. ModifiedDate = DateTime.Now
  30. };
  31. db.People.Add(stephen);
  32. db.People.Attach(stephen);
  33. //db.Entry(stephen).State = EntityState.Unchanged;//同上面db.People.Attach(stephen);作用一样
  34. db.SaveChanges();
  35. }
  36. }
  37. }
  38. }

使用”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的删除操作:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9. using System.Data.Objects;
  10.  
  11. namespace EFPowerTools
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16.  
  17. {
  18. using (var db = new AdventureWorksContext())
  19. {
  20. var mail = db.EmailAddresses.Where(m => m.EmailAddressID == 19977).FirstOrDefault();
  21. db.EmailAddresses.Remove(mail);
  22. db.SaveChanges();
  23. }
  24. }
  25. }
  26. }

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9. using System.Data.Objects;
  10.  
  11. namespace EFPowerTools
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16.  
  17. {
  18. using (var db = new AdventureWorksContext())
  19. {
  20. var mail = db.EmailAddresses.Where(m => m.EmailAddressID == 19976).FirstOrDefault();
  21. db.Entry(mail).State = EntityState.Deleted;
  22. db.SaveChanges();
  23. }
  24. }
  25. }
  26. }

修改

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Entity.Validation;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using EFPowerTools.Models;
  9. using System.Data.Objects;
  10.  
  11. namespace EFPowerTools
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16.  
  17. {
  18. using (var db = new AdventureWorksContext())
  19. {
  20. var person = db.People.Where(p => p.LastName == "Stevens").OrderBy(p=>p.BusinessEntityID).FirstOrDefault();
  21. person.NameStyle = false;
  22. person.EmailAddresses.First().EmailAddress1 = "KenshinCui@outlook.com";
  23. db.SaveChanges();
  24. }
  25. }
  26. }
  27. }

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

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

转载Entity Framework 5.0(EF first)中的添加,删除,修改,查询,状态跟踪操作的更多相关文章

  1. 在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 ...

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

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

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

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

  4. Entity Framework 5.0

    今天 VS2012  .net Framework 4.5   Entity Framework 5.0  三者共同发布了. ( EF5 Released ) 在介绍新特性之前,先与大家回顾一下EF版 ...

  5. 云优化的概念、Entity Framework 7.0、简单吞吐量压力测试

    云优化的概念.Entity Framework 7.0.简单吞吐量压力测试 继续上一篇<开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1)>之 ...

  6. 浅析Entity Framework Core2.0的日志记录与动态查询条件

    前言 Entity Framework Core 2.0更新也已经有一段时间了,园子里也有不少的文章.. 本文主要是浅析一下Entity Framework Core2.0的日志记录与动态查询条件 去 ...

  7. Entity Framework Core(EF Core) 最简单的入门示例

    目录 概述 基于 .NET Core 的 EF Core 入门 创建新项目 更改当前目录 安装 Entity Framework Core 创建模型 创建数据库 使用模型 基于 ASP.NET Cor ...

  8. Entity Framework 6.0 常见异常及解决办法

    Ø  简介 本文主要记录 EF(Entity Framework) 在平时的开发中可能遇到的异常,以及应该如何去解决. 1.   System.InvalidOperationException 1) ...

  9. Asp.Net MVC4开发二: Entity Framework在Asp.Net MVC4中的应用

    ORM作为一种数据库訪问机制已广泛地应用于各种项目其中,在.Net开发中,应用比較广泛的ORM框架大致有以下几个: 官方支持的有:Linq to SQL.Entity Framework.三方的有:N ...

随机推荐

  1. [扫描线]POJ2932 Coneology

    题意:有n个圆 依次给了半径和圆心坐标  保证输入的圆不相交(只有 相离 和 内含/外含 的情况)   问 有几个圆 不内含在其他圆中,并分别列出这几个圆的编号(1~n) (n的范围是[1, 4000 ...

  2. mongoDB入门必读

    一.概述 MongoDB是一个基于分布式文件存储的数据库开源项目. 由C++语言编写,旨在为WEB应用提供可护展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品. ...

  3. 【HDOJ】4343 Interval query

    最大不相交集合的数量.思路是dp[i][j]表示已经有i个不相交集合下一个不相交集合的最右边界.离散化后,通过贪心解. /* 4343 */ #include <iostream> #in ...

  4. sed awk 要获得每行的最后一个逗号后边的内容

    获得每行的最后一个逗号后边的内容.例如:KIAA1967 KIAA1967, xxxxSECIS biding proin 2-like, SECISBP2L, yyyy 1234ankyrin re ...

  5. sed找到重复的行

    sed之仅打印相邻重复的行 cat file  aaa bbb bbb ccc ddd eee eee fff   只显示重复的行: bbb bbb eee eee   sed -n ':a;N;/\ ...

  6. Java中Scanner类

    java.util.Scanner类,这是一个用于扫描输入文本的新的实用程序

  7. Managed C++中使用Nullable<T>

    非null值表示和C#的用法一样. Nullable<int> a = 1; null值的表示: Nullable<int> a = Nullable<int>() ...

  8. poj2886Who Gets the Most Candies? (约瑟夫环)

    http://poj.org/problem?id=2886 单点更新 初始位置都是1 如果这个人出去 位置变为0 利用线段树求区间k值 k值的计算如下 如果这个数值是负的 那么下一个人的就是((k- ...

  9. poj 2409 Let it Bead && poj 1286 Necklace of Beads(Polya定理)

    题目:http://poj.org/problem?id=2409 题意:用k种不同的颜色给长度为n的项链染色 网上大神的题解: 1.旋转置换:一个有n个旋转置换,依次为旋转0,1,2,```n-1. ...

  10. [原]Unity3D深入浅出 - 新版粒子系统 (Shuriken)

    Shuriken粒子系统是继Unity3.5版本之后推出的新版粒子系统,它采用了模块化管理,个性化的粒子模块配合粒子曲线编辑器使用户更容易创作出各种兵分复杂的粒子效果. 创建一个粒子系统的方式有两种: ...