如何使用Entity Framework在多层应用程序中正确管理ObjectContext生命周期? [英] How to manage ObjectContext lifetime correctly in multi-tier application using Entity Framework?

查看:167
本文介绍了如何使用Entity Framework在多层应用程序中正确管理ObjectContext生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在MVC3应用程序中看到了许多使用Entity Framework的例子,他们是非常简单的演示,只有一个mvc3 web项目,里面有edmx。



可以通过using语句使用最佳实践来打开和关闭连接:

  using(var context = new SchoolEntities 
{
//做一些查询并返回带有结果的View。
}

并且,它可以使用延迟加载因为上下文还没有
处理:

  foreach(student.Course中的var项)
{
//使用导航属性执行操作Course
}

所有的东西似乎都是完美的,直到它成为一个n层应用程序。



我创建了DAL,BLL和MVC3 UI。



在其中有edmx,以及操作符类如 SchoolDA.cs:

  public class StudentDA b $ b {
public Student FindStudent(int studentId)
{
using(var context = new SchoolContext())
{
//查询,返回学生对象。
}
}
}

如果我使用:

  var student = studentDa.FindStudent(103); 

然后调用导航属性

  student.Course 

得到一个错误(当然):



ObjectContext实例已被处理,不能再用于需要连接的操作。 / p>

所以,我必须这样改变StudentDA.cs:

  public class StudentDA():IDisposable 
{
private SchoolEntites context;

public StudentDA()
{
context = new SchoolEntities();
}

public void Dispose()
{
context.Dispose();
}

public Student FindStudent(int studentId)
{
//查询,返回学生对象。然后,BLL将改变如下:
}
}

  public Student FindStudent(int id)
{
using(var studentDa = new StudentDA())
{
//这可以访问导航属性没有错误,并正确关闭连接。
return studentDa.FindStudent(id);
}
}

所有东西似乎都是完美的,直到它满足更新()方法。



现在,如果我想更新从BLL.FindStudent()获取的学生对象, context.SaveChanges 0,因为上下文已经在BLL.FindStudent()中处理,并且不会更新到数据库。

  var optStudent = new StudentBO(); 
var student = optStudent.FindStudent(103);
student.Name =NewValue;
optStudent.Update(student);

有谁知道如何在3轮胎应用程序中使用EntityFramework?或者如何正确地管理上下文。我将经常在web层中使用导航属性,但是我不能总是保持连接打开以使用服务器内存。

解决方案

有多种方法来处理EF上下文的生命周期。在web应用中,通常上下文对于HttpRequest是唯一的。例如,如果你想在一个Web应用程序中手动处理,并且有一个每个Thread / HttpRequest EF上下文,你可以这样做与下面(代码复制从 http://www.west-wind.com/weblog/posts/2008/Feb/ 05 / Linq-to-SQL-DataContext-Lifetime-Management ):

 内部静态类DbContextManager 
{
public static DbContext Current
{
get
{
var key =MyDb_+ HttpContext.Current.GetHashCode()。ToString(x)
+ Thread.CurrentContext.ContextID.ToString();
var context = HttpContext.Current.Items [key] as MyDbContext;

if(context == null)
{
context = new MyDbContext();
HttpContext.Current.Items [key] = context;
}
return context;
}
}
}

  var ctx = DbContextManager.Current 

但我建议您将终身管理留给IoC框架,如 Autofac Castle Windsor Ninject ,它会自动处理您注册的对象的创建/处置以及许多其他功能。


I have seen many examples using Entity Framework in MVC3 applications, they are very simple demos which only have one mvc3 web project with edmx inside it.

So, they can use the best practice for open and close connection by "using" statement:

using(var context = new SchoolEntities())
{
    // do some query and return View with result.
}

And, It can use lazy load (navigation properties) inside the "using" statment correctly, because the context is not yet disposed:

foreach(var item in student.Course)
{
    // do something with the navigation property Course
}

All things seems to be perfect until it becomes an n-tier application.

I created DAL, BLL, and a MVC3 UI.

The DAL have edmx inside it, and operator classes like SchoolDA.cs:

public class StudentDA()
{
    public Student FindStudent(int studentId)
    {
        using(var context = new SchoolContext())
        {
            // do query, return a student object.
        }
    }
}

Then, in the BLL, if I use:

var student = studentDa.FindStudent(103);

then invoke it's navigation property:

student.Course

I will get an error (of course):

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

So, I have to change StudentDA.cs like this:

public class StudentDA() : IDisposable
{
    private SchoolEntites context;

    public StudentDA()
    {
        context = new SchoolEntities();
    }

    public void Dispose()
    {
        context.Dispose();
    }

    public Student FindStudent(int studentId)
    {
        // do query, return a student object.
    }
}

Then, the BLL will change like this:

public Student FindStudent(int id)
{
    using(var studentDa = new StudentDA())
    {
        // this can access navigation properties without error, and close the connection correctly.
        return studentDa.FindStudent(id);
    }
}

All things seem to be perfect again until it meet Update() method.

Now, if I want to update a student object which is taken from BLL.FindStudent(), the context.SaveChanges() will return 0, because the context is already disposed in the BLL.FindStudent(), and nothing will be updated to database.

var optStudent = new StudentBO();
var student = optStudent.FindStudent(103);
student.Name = "NewValue";
optStudent.Update(student);

Does anyone have idea on how to use EntityFramework in 3 tire application? or how can I manage the context correctly. I will use navigation propertites very often in the web layer, but I can't always remain connection open to consume the server memory.

解决方案

There are multiple ways to handle EF context's lifetime. In web apps, usually context is unique for an HttpRequest. For example, if you want to handle this manually in a web application and have a per Thread/HttpRequest EF context, you can do so with the following (Code copied from http://www.west-wind.com/weblog/posts/2008/Feb/05/Linq-to-SQL-DataContext-Lifetime-Management):

internal static class DbContextManager
{
    public static DbContext Current
    {
        get
        {
            var key = "MyDb_" + HttpContext.Current.GetHashCode().ToString("x")
                      + Thread.CurrentContext.ContextID.ToString();
            var context = HttpContext.Current.Items[key] as MyDbContext;

            if (context == null)
            {
                context = new MyDbContext();
                HttpContext.Current.Items[key] = context;
            }
            return context;
        }
    }
}  

And then you can easily use:

var ctx = DbContextManager.Current

But I suggest you leave the lifetime management to an IoC framework like Autofac, Castle Windsor, or Ninject which automatically handle the creation/disposal of your registered obejcts along with many other features.

这篇关于如何使用Entity Framework在多层应用程序中正确管理ObjectContext生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆