我已经阅读了很多文章,解释如何设置实体框架的DbContext,以便使用各种DI框架只创建和使用每个HTTP web请求。
为什么一开始这是个好主意?使用这种方法有什么好处?在某些情况下,这是个好主意吗?在每个存储库方法调用实例化dbcontext时,是否有一些事情是使用这种技术可以做而不能做的?
我已经阅读了很多文章,解释如何设置实体框架的DbContext,以便使用各种DI框架只创建和使用每个HTTP web请求。
为什么一开始这是个好主意?使用这种方法有什么好处?在某些情况下,这是个好主意吗?在每个存储库方法调用实例化dbcontext时,是否有一些事情是使用这种技术可以做而不能做的?
当前回答
实体框架需要特别注意的另一个问题是,当组合使用创建新实体、延迟加载,然后使用这些新实体时(从相同的上下文中)。如果你不使用IDbSet。创建(vs只是新建),当它从创建它的上下文检索时,对该实体的惰性加载将不起作用。例子:
public class Foo {
public string Id {get; set; }
public string BarId {get; set; }
// lazy loaded relationship to bar
public virtual Bar Bar { get; set;}
}
var foo = new Foo {
Id = "foo id"
BarId = "some existing bar id"
};
dbContext.Set<Foo>().Add(foo);
dbContext.SaveChanges();
// some other code, using the same context
var foo = dbContext.Set<Foo>().Find("foo id");
var barProp = foo.Bar.SomeBarProp; // fails with null reference even though we have BarId set.
其他回答
我喜欢它的地方在于,它将工作单元(正如用户看到的那样——即页面提交)与ORM意义上的工作单元对齐。
因此,您可以使整个页面提交都是事务性的,如果您公开CRUD方法,并且每个方法都创建一个新的上下文,则无法做到这一点。
实体框架需要特别注意的另一个问题是,当组合使用创建新实体、延迟加载,然后使用这些新实体时(从相同的上下文中)。如果你不使用IDbSet。创建(vs只是新建),当它从创建它的上下文检索时,对该实体的惰性加载将不起作用。例子:
public class Foo {
public string Id {get; set; }
public string BarId {get; set; }
// lazy loaded relationship to bar
public virtual Bar Bar { get; set;}
}
var foo = new Foo {
Id = "foo id"
BarId = "some existing bar id"
};
dbContext.Set<Foo>().Add(foo);
dbContext.SaveChanges();
// some other code, using the same context
var foo = dbContext.Set<Foo>().Find("foo id");
var barProp = foo.Bar.SomeBarProp; // fails with null reference even though we have BarId set.
我很确定这是因为DbContext根本不是线程安全的。所以分享从来不是个好主意。
这里没有一个答案能真正回答这个问题。OP并没有询问单例/每个应用程序的DbContext设计,他询问了每个(web)请求的设计以及可能存在的潜在好处。
我会参考http://mehdi.me/ambient-dbcontext-in-ef6/,因为Mehdi是一个很棒的资源:
Possible performance gains. Each DbContext instance maintains a first-level cache of all the entities its loads from the database. Whenever you query an entity by its primary key, the DbContext will first attempt to retrieve it from its first-level cache before defaulting to querying it from the database. Depending on your data query pattern, re-using the same DbContext across multiple sequential business transactions may result in a fewer database queries being made thanks to the DbContext first-level cache. It enables lazy-loading. If your services return persistent entities (as opposed to returning view models or other sorts of DTOs) and you'd like to take advantage of lazy-loading on those entities, the lifetime of the DbContext instance from which those entities were retrieved must extend beyond the scope of the business transaction. If the service method disposed the DbContext instance it used before returning, any attempt to lazy-load properties on the returned entities would fail (whether or not using lazy-loading is a good idea is a different debate altogether which we won't get into here). In our web application example, lazy-loading would typically be used in controller action methods on entities returned by a separate service layer. In that case, the DbContext instance that was used by the service method to load these entities would need to remain alive for the duration of the web request (or at the very least until the action method has completed).
记住,也有缺点。这个链接包含了许多关于这个主题的其他资源。
我把这篇文章贴出来,以防别人偶然发现这个问题,并没有被那些并没有真正解决这个问题的答案所吸引。
Another understated reason for not using a singleton DbContext, even in a single threaded single user application, is because of the identity map pattern it uses. It means that every time you retrieve data using query or by id, it will keep the retrieved entity instances in cache. The next time you retrieve the same entity, it will give you the cached instance of the entity, if available, with any modifications you have done in the same session. This is necessary so the SaveChanges method does not end up with multiple different entity instances of the same database record(s); otherwise, the context would have to somehow merge the data from all those entity instances.
这是一个问题,因为单例DbContext会成为一个定时炸弹,最终会缓存整个数据库和。net对象在内存中的开销。
只有通过使用. notracking()扩展方法来使用Linq查询,才能避免这种行为。而且现在的电脑有很多内存。但这通常不是理想的行为。