EntityFramework上下文实现错误?

时间:2012-03-15 13:47:40

标签: entity-framework c#-4.0 ef-code-first datacontext

我首先为EF 4.2代码工作,并且已经遇到了很多随机的上下文连接问题,并且想知道你是否可以关注这个实现,然后拍我的手腕做错了(如果是错的话) )

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

我确信我这样做的方法是问题,但无论如何这里是代码:

Context Provider

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 Class

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

    }

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

2 个答案:

答案 0 :(得分: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>(); } }
}

答案 1 :(得分:-1)

对于单例模式,有一个非常有用的通用实现Lazy:

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;} 
    } 
 } 

正如其他人已经指出的那样 - 不建议使用静态上下文,而是为每个操作创建\配置它。