Entity Framework 4.1/4.3 之四(DBContext 之 1 DBContext 是谁)
伦敦奥运如火如荼的开幕了,人们还是愿意拿来和北京奥运小比一下,大多仁者见仁,智者见智。说的都还有理。在此预祝伦敦奥运圆满结束,毕竟我是007的忠实Fans。
大家还记得Entity Framework 4.1/4.3 之一(概念篇)中我介绍过ObjectContext ObjectSet 以及 DBContext 和DBSet的定义。在使用了4.0很长一段时间后,我向4.3进行了过渡,这个过渡的过程中,我认识并使用了 DBContext 和 DBSet 。感觉很不错。下面我通会表格来分别展示一下ObjectContext ObjectSet DBContext DBSet:
DbContext |
Relevant EF4 feature/class (有关EF4中的功能/类) |
General purpose(共同的作用) | Benefit of DbContext API (DBContext API 的优势) |
DbContext | ObjectContext | Represent a session with the database. Provide (与数据库进行会话) |
Exposes and simplifies most (简化ObjectContext中的常用功能) |
DbSet | ObjectSet | Provide set operations for entity types, such as Add, (提货对数据实体的操作,如增、改、查,继承了DBQuery的一些功能) |
Exposes and simplifies most (简化ObjectSet中的常用功能) |
DbQuery | ObjectQuery | Provide querying capabilities (提供查询功能) |
The query functionality of () |
Change Tracker API |
ObjectContext. ObjectStateManager |
Get access to change tracking information and operations (获取发生的跟踪信息和操作(例如,原始值,当前值)并进行管理。) |
Simpler and more intuitive API (简化更多API使用) |
Validation API | n/a | Provide automatic validation of data at the data (提供自动化的数据验证,验证功能在.Net4已经存在) |
New to DbContext API.
|
Code First Model Building |
n/a | Reads classes and code-based configurations to build (代码先行) |
New to DbContext API.
|
通过上面表格的介绍,我们应该可以明白 DBContext DBSet 的作用了。
如何在我们的项目中使用DBContext呢?我们可以使用NuGet工具,来获取DBContext,NuGet工具我已经在前面的博文中进行了介绍(大家也可以通过百度来查一下)。下面附上一张如何使用EF4.3的图(即如何添加包含DBContext的引用)。
一、DBContext API的一些亮点
DBContext API 主要是针对实体框架交互的简化。DBContext API相对于以前的实体框架(EF)版本减少了方法和属性的数量。优化了数据查询及实体操作方面的功能。下面我们通过一些实例来看看,DBContext API是如何简化的优化的。交且我们会也 ObjectContext API 进行一些直观的对比。
(1)、ObjectContext 例子
1 public class BreakAwayContext : ObjectContext 2 { 3 private ObjectSet<Person> _ people; 4 private ObjectSet<Destination> _destinations; 5 private ObjectSet<Trip> _trips; 6 public ObjectSet<Person> People 7 { 8 get { return _people ?? (_people = CreateObjectSet<Person>("People")); } 9 } 10 public ObjectSet< Destination > Contacts 11 { 12 get { return _ destinations?? (_destinations =
13 CreateObjectSet< Destination >("Destinations")); } 14 } 15 public ObjectSet<Trip> Trips 16 { 17 get { return _ trips?? (_trips = CreateObjectSet<Trip>("Trips")); } 18 } 19 }
代码中显示了一个用EF4定义的BreakAwayContext类,它继续ObjectContext。它将子集包装成ObjectSets类型。
这么说大家可能有点糊涂,我来讲的通俗点,BreakAwayContext就相当于一个大的容器,它里面装着从ObjectContext中继承来的实体操作方法。同时,它里面还装着实体子集(其实就是数据库中对应的表,比如Student表,Teacher表),这些子集的类型是ObjectSet,有了这些子集后,在与数据库的会话中,我们便可以对其进行操作,来获取我们自己想要的数据。上面的代码展示了老版本中的ObjectContext 的应用实例。
(2)、DBContext的例子
1 public class BreakAwayContext : DbContext 2 { 3 public DbSet<Person> People { get; set; } 4 public DbSet<Destination> Destinations { get; set; } 5 public DbSet<Trip> Trips { get; set; } 6 }
对比中发现,DBContext 它将子集包装成DBSet类型。DBContext使用代码更加整洁,在DBContext中CreateDbSet与CreateObjectSet有着一样的功能。
(3)、方法上的改进
ObjectContext和ObjectSet都提供了AddObject的功能:
比如 context.AddObject("Students", newStudent):
context.Students.AddObject(newStudent):
而 DBContext中则只有DBSet有这个功能,并且名称为成了Add
context.Students.Add(newStudent):
对比发现,Add的操作本身就是对实体的操作,但是ObjectContext和ObjectSet中都有AddObject方法,实在是有点不直观并且还有点多余。所以DBContext中对他进行了简化,就只能DBSet中有Add的方法。
(4)、单条实体记录的查询改进。(即我们根据ID来查询一条记录)
context.People.SingleOrDefault(p => p.PersonId == _personId)
这是早期我们比较长用到的一上方法,但是DBSet给我们提供了更为简洁的方法,如下:
context.People.Find(_personId)
怎么样,简单吧!但是有一点要强调,_personId 要求是主键,只有这样,才可以使用Find方法。
还有一个优点:SingleOrDefault方法会直接执行数据库查询,而Find刚会先去缓存中查询,如果没有的话,才执行数据库查询。感觉不错吧。
(5)、DBCotext 中查询
遍历全部
private static void PrintAllDestinations() { using (var context = new BreakAwayContext()) { foreach (var destination in context.Destinations) { Console.WriteLine(destination.Name); } } }
排序
private static void PrintAllDestinationsSorted() { using (var context = new BreakAwayContext()) { var query = from d in context.Destinations orderby d.Name select d; foreach (var destination in query) { Console.WriteLine(destination.Name); } } }
本地查询 (会去缓存找是否存在用户想要的数据)
private static void GetLocalDestinationCount() { using (var context = new BreakAwayContext()) { var count = context.Destinations.Local.Count; Console.WriteLine("Destinations in memory: {0}", count); } }
使用Load 方法将数据放入缓存中
private static void GetLocalDestinationCountWithLoad() { using (var context = new BreakAwayContext()) { context.Destinations.Load(); var count = context.Destinations.Local.Count; Console.WriteLine("Destinations in memory: {0}", count); } }
我们也可以把一些查询结果也放入到缓存中,同样是使用Load方法
private static void LoadAustralianDestinations() { using (var context = new BreakAwayContext()) { var query = from d in context.Destinations where d.Country == "Australia"
select d; query.Load(); var count = context.Destinations.Local.Count; Console.WriteLine("Aussie destinations in memory: {0}", count); } }
延迟加载
private static void TestLazyLoading() { using (var context = new BreakAwayContext()) { var query = from d in context.Destinations where d.Name == "Grand Canyon"
select d; var canyon = query.Single(); Console.WriteLine("Grand Canyon Lodging:"); if (canyon.Lodgings != null) { foreach (var lodging in canyon.Lodgings) { Console.WriteLine(lodging.Name); } } } }
关于延迟加载我必须强调一上,延迟加载的使用必需要保证在一下数据库连接打来的情况下。就是在using(){ 对延迟加载的实体只能在这个范围中使用,因为数据库连接一旦关闭,则无法使用了。 }
预先加载 (请注意Include方法)
private static void TestEagerLoading() { using (var context = new BreakAwayContext()) { var allDestinations = context.Destinations.Include(d => d.Lodgings); foreach (var destination in allDestinations) { Console.WriteLine(destination.Name); foreach (var lodging in destination.Lodgings) { Console.WriteLine(" - " + lodging.Name); } } } }
好了,今天就选写这么多,后续还会写DBContext之二,进行知识补充。由于写文字进行说明太费时,有的时候还容易导致大家理解错误。所以我主要以代码来进行说明。希望对大家有用,我是百灵。
百灵注:本文版权由百灵和博客园共同所有,转载请注明出处。
助人等于自助! [email protected]