Entity Framework 4.1/4.3 之四(DBContext 之 1 DBContext 是谁)

大家还记得Entity Framework 4.1/4.3 之一(概念篇)中我介绍过ObjectContext ObjectSet 以及 DBContext 和DBSet的定义。在使用了4.0很长一段时间后,我向4.3进行了过渡,这个过渡的过程中,我认识并使用了 DBContext 和 DBSet 。感觉很不错。下面我通会表格来分别展示一下ObjectContext ObjectSet DBContext DBSet:

DbContext
API feature (DbContext API功能)

Relevant EF4
feature/class (有关EF4中的功能/类)
General purpose(共同的作用) Benefit of DbContext API (DBContext API 的优势)
DbContext ObjectContext

Represent a session with the database. Provide
query, change tracking and save capabilities

(与数据库进行会话)

Exposes and simplifies most
commonly used features of ObjectContext.

(简化ObjectContext中的常用功能)

DbSet ObjectSet

Provide set operations for entity types, such as Add,
Attach and Remove. Inherits from DbQuery to expose
query capabilities.

(提货对数据实体的操作,如增、改、查,继承了DBQuery的一些功能)

Exposes and simplifies most
commonly used features of ObjectSet.

(简化ObjectSet中的常用功能)

DbQuery ObjectQuery

Provide querying capabilities

(提供查询功能)

The query functionality of
DbQuery is exposed on DbSet, so
you don’t have to interact with
DbQuery directly.

()

Change
Tracker API
ObjectContext.
ObjectStateManager

Get access to change tracking information and operations
(e.g., original values, current values) managed
by the context.

(获取发生的跟踪信息和操作(例如,原始值,当前值)并进行管理。)

Simpler and more intuitive API
surface.

(简化更多API使用)

Validation API n/a

Provide automatic validation of data at the data
layer. This API takes advantage of validation features
already existing in .NET 4.

(提供自动化的数据验证,验证功能在.Net4已经存在)

New to DbContext API.

 

Code First
Model
Building
n/a

Reads classes and code-based configurations to build
in-memory model, metadata and relevant database.

(代码先行)

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 例子

        View Code
澶嶅埗浠g爜
 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 }
澶嶅埗浠g爜

          代码中显示了一个用EF4定义的BreakAwayContext类,它继续ObjectContext。它将子集包装成ObjectSets类型。
          这么说大家可能有点糊涂,我来讲的通俗点,BreakAwayContext就相当于一个大的容器,它里面装着从ObjectContext中继承来的实体操作方法。同时,它里面还装着实体子集(其实就是数据库中对应的表,比如Student表,Teacher表),这些子集的类型是ObjectSet,有了这些子集后,在与数据库的会话中,我们便可以对其进行操作,来获取我们自己想要的数据。上面的代码展示了老版本中的ObjectContext 的应用实例。

      (2)、DBContext的例子

      View Code
澶嶅埗浠g爜
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 }
澶嶅埗浠g爜

          对比中发现,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之二,进行知识补充。由于写文字进行说明太费时,有的时候还容易导致大家理解错误。所以我主要以代码来进行说明。希望对大家有用,我是百灵。

     

 

百灵注:本文版权由百灵和博客园共同所有,转载请注明出处。      

助人等于自助!  mbailing@163.com

原文地址:https://www.cnblogs.com/zhangchenliang/p/2847373.html