应该在每个事务上创建EF dbContext

时间:2014-11-14 05:24:12

标签: c# .net entity-framework dbcontext

我正在试图找出管理DbContext的最佳方法。我见过代码样本没有处理,我看到有人说这是个坏主意。做下面的事情对我来说是否合适?另外,我应该将每个事务(包括读取)放在新的DbContext中吗?这可能是另一个问题,但关于EntityState的部分是必要的吗?

public abstract class GenericRepository<T> where T : EntityData
{
    protected MyDbContext Context
    {
        get { return new MyDbContext(); }
    }

    public T Save(T obj)
    {
        T item;
        using (var context = Context)
        {
            var set = context.Set<T>();

            if (String.IsNullOrEmpty(obj.Id))
                item = set.Add(obj);
            else
            {
                item = set.Find(obj.Id);
                item = obj;
            }

            // taken from another code sample
            var entry = context.Entry(item);
            if (entry.State == EntityState.Detached)
            {
                //Need to set modified so any detached entities are updated 
                // otherwise they won't be sent across to the db. 
                // Since it would've been outside the context, change tracking 
                //wouldn't have occurred anyways so we have no idea about its state - save it!
                set.Attach(item);
                context.Entry(item).State = EntityState.Modified;
            }
            context.SaveChanges();
        }

        return item;
    }
}

修改
我还有一个扩展类,它在下面实现了这个功能。上下文没有包含在此查询中的using语句中,所以我对我的代码有点怀疑。

public IQueryable<T> FindByAccountId(string accountId)
{
    return from item in Context.Set<T>()
        let user = UserRepository.FindByAccountId(accountId).FirstOrDefault() 
        where item.UserId == user.Id
        select item;
}

2 个答案:

答案 0 :(得分:3)

上下文应该基于每个请求。请求进入并创建新的上下文。该上下文用于请求的其余部分,然后相应地在请求结束时处理。这为您提供了请求长事务的好处,并且正如HamidP所强调的那样,您还可以获得缓存实体的额外好处;这意味着加载到上下文中的任何实体都可以通过检索加载,而不需要查询数据库的实体框架。

如果您正在使用任何类型的控制容器反转,例如StructureMap,那么您可以通过以下配置轻松创建HTTP请求绑定上下文:

this.For<DbContext>().HybridHttpOrThreadLocalScoped().Use<DbContext>();

然后您可以将DbContext(或其衍生物)注入您的存储库,并将您选择的IOC容器留在请求结束时处理上下文。如果您要将相同的上下文注入另一个存储库,那么您将收到相同的上下文实例。

我希望这有帮助!

答案 1 :(得分:1)

不,它不应该

此处的最佳方法是仅为请求分配上下文。您应该将上下文附加到传入的请求,并在请求完成时处理您的上下文。在这种方法中,您可以节省为每个事务创建上下文的开销,并且还可以从上下文的缓存机制中受益,因为每个上下文都有内部缓存,请求可以访问它最近访问过的数据。

为每笔交易创建一个上下文并不像拥有长生命周期那样糟糕! 不要这样做,长寿命上下文导致许多并发问题,缓存变得陈旧,内存消耗也越来越高,你应该在未来通过奇迹维护你的应用程序。