2012-03-15 23 views
0

我正在为EF 4.2代码第一次工作,并且已经获得了很多随机上下文连接问题,并且想知道如果您能够关注此实现,然后拍我的手腕来做这件事是错误的(如果它是错误的)EntityFramework上下文实现错误?

我为这个项目开发了一个存储库模式。

我相信我做的方式是问题,但无论如何,这里是代码:

境提供

public class ContextProvider 
{ 
    private static MyContext context; 
    public static MyContext Context 
    { 
     get 
     { 
      if (context == null) 
      { 
       context = new MyContext(); 
      } 

      Database.SetInitializer<MyContext>(null); 

      //create the DB if it doesn't exist 
      if (!context.Database.Exists()) 
      { 
       context.Database.Create(); 
       context = new MyContext(); 
      } 

      return context; 

     } 
    } 
} 

这里是我的仓库:

public class DataRepository 
{ 
    protected MyContext Context; 

    public DataRepository(MyContext context = null) 
    { 
     Context = context ?? ContextProvider.Context; 
    } 

    public ProviderBase<Foo> FooProvider { get { return new ProviderBase<Foo>(); } } 
    public ProviderBase<Bah> BahProvider { get { return new ProviderBase<Bah>(); } } 

} 

的ProviderBase类

public class ProviderBase<T> : IProviderBase<T> where T : BaseClass 
    { 
     public Boolean UseCaching { get; set; } 

     public MyContext Context; 

     public ProviderBase(Boolean useCaching = true, MyContext context = null) 
     { 
      Context = context ?? ContextProvider.Context; 
      UseCaching = useCaching; 
     } 

     #region Implementation of IProviderBase<T> 

     protected DbSet<T> DbSet 
     { 
      get 
      { 
       return Context.Set<T>(); 
      } 
     } 

     ... methods here for CRUD .... 

    } 

我认为问题是静态的上下文,我说得对吗?如果是的话,解决方案是什么?

+0

http://stackoverflow.com/search?q=static+objectcontext – 2012-03-15 13:53:00

+1

@ Craig感谢您展示如何使用SO的搜索功能,但我非常了解它。我已经阅读了数百篇关于SO和其他站点的文章,但是我对于解决我的问题感到茫然,因此我发布了这个问题。建设性回复比仅仅发布链接更有帮助... – JamesStuddart 2012-03-15 13:56:11

+0

您正在构建什么类型的应用程序? – 2012-03-15 14:13:50

回答

4

Don't use static context

要修改你的代码,你可以使用这个:

public class ContextProvider 
{ 
    private const string ContextId = "EF.MyContext"; 

    // Call this only once in Application_Start in Global.asax 
    public void InitializeDatabase() 
    { 
     MyContext context = GetContext(); 
     if (!context.Database.Exists()) 
     { 
      context.Database.Create(); 
     } 
    } 

    public MyContext GetContext() 
    { 
     MyContext context = HttpContext.Current.Items[ContextId] as MyContext; 

     if (context == null) 
     { 
      context = new MyContext(); 
      HttpContext.Current.Items[CotnextId] = context; 
     } 

     return context; 
    } 

    // Call this in EndRequest handler in Global.asax 
    public void ReleaseContext() 
    { 
     MyContext context = HttpContext.Current.Items[ContextId] as MyContext; 

     if (context != null) 
     { 
      context.Dispose(); 
     } 
    } 
} 

而且你的仓库将是这样的:

public class DataRepository 
{ 
    protected MyContext Context; 

    // If you never need more than one instance of MyContext per repository you 
    // can inject context directly and call provider in upper layer 
    public DataRepository(ContextProvider provider) 
    { 
     Context = provider.GetContext(); 
    } 

    public ProviderBase<Foo> FooProvider { get { return new ProviderBase<Foo>(); } } 
    public ProviderBase<Bah> BahProvider { get { return new ProviderBase<Bah>(); } } 
} 
+0

谢谢,这看起来像我正在寻找的解决方案,我已经实现了它,只需要测试它。 感谢您的帮助。 – JamesStuddart 2012-03-16 10:56:00

+0

我刚刚给出了这个测试,我得到以下错误: 该操作无法完成,因为DbContext已被处置。 我知道这是由于在Application_EndRequest 中关闭了dbContext的任何建议吗? – JamesStuddart 2012-03-16 11:02:44

+0

这意味着你在某处放置了上下文。 'EndRequest'后面不应该使用上下文。 – 2012-03-16 11:07:11

-1

对于单patterm有非常有用的通用实现懒惰:

public class ContextProvider 
{ 
    private static Lazy<MyContext> _context = new Lazy<MyContext> context(CreateContext); 

    private static MyContext CreateContext() 
    { 
      var context = new MyContext(); 

      Database.SetInitializer<MyContext>(null); 

      //create the DB if it doesn't exist 
      if (!context.Database.Exists()) 
      { 
       context.Database.Create(); 
      } 

      return context; 
    } 

    public static MyContext Context 
    { 
     get { return _context.Value;} 
    } 
} 

也为他人已经指出来你 - 这是不推荐使用静态上下文,而是创建\处置它为每个操作。