我对实体框架比较陌生,我能找到的所有文档或书籍都在谈论如何使用框架,或者应该使用哪种模型,但没有深入解释框架是如何工作的。
例如,当我通过 LINQ 查询或框架方法从数据库加载实体时,这些实体是线程安全的吗?换句话说,它们可以与其他线程共享吗?如果是这样,EF如何控制一致性?
当控制脱离上下文时,这些实体是消失了还是仍在记忆中?在 .SaveChanges 之后,那些实体消失了吗?生命周期是什么?
请EF专家详细解释以上几点。
提前致谢。
我对实体框架比较陌生,我能找到的所有文档或书籍都在谈论如何使用框架,或者应该使用哪种模型,但没有深入解释框架是如何工作的。
例如,当我通过 LINQ 查询或框架方法从数据库加载实体时,这些实体是线程安全的吗?换句话说,它们可以与其他线程共享吗?如果是这样,EF如何控制一致性?
当控制脱离上下文时,这些实体是消失了还是仍在记忆中?在 .SaveChanges 之后,那些实体消失了吗?生命周期是什么?
请EF专家详细解释以上几点。
提前致谢。
已加载实体的生命周期或多或少与加载它们的实体上下文相关。因此,在许多示例中,您将看到:
using (var ctx = new Context())
{
// ... do work
} // The context gets disposed here.
一旦上下文被释放(例如在语句的末尾using
),您不应再将在上下文中加载的实体视为可以从它们加载附加信息。例如,不要尝试访问它们的导航属性。为避免出现问题,我通常发现最好创建一个 DTO,它只包含我希望人们能够使用的确切数据,并且将其作为using
声明中唯一的值。
using (var ctx = new Context())
{
var q = from p in ctx.People
select new PersonSummary{Name = p.Name, Email = p.Email};
return q.ToList(); // This will fully evaluate the query,
// leaving you with plain PersonSummary objects.
}
实体上下文不是线程安全的,因此即使在上下文的生命周期内,也不应该尝试从多个线程中为绑定到同一上下文的对象加载导航属性等。
例如,当我通过 LINQ 查询或框架方法从数据库加载实体时,这些实体是线程安全的吗?换句话说,它们可以与其他线程共享吗?如果是这样,EF如何控制一致性?
ObjectContext 类并不安全。每个线程必须有一个对象上下文或创建自己的线程同步过程。这样,一致性由 ObjectContext 管理,因为它跟踪所有对象的状态。
当控制脱离上下文时,这些实体是消失了还是仍在记忆中?在 .SaveChanges 之后,那些实体消失了吗?生命周期是什么?
ObjectContext 类继承自 IDisposable 接口,因此您可以并且应该在使用实体框架时使用 USING 语句。这样,在您关闭 using 语句后它们就消失了。如果您不处理它们一直被跟踪的上下文,则只会更改它们的状态。释放 ObjectContext 实例还将确保正确释放数据库连接并且不会泄漏数据库连接。
所以,最大的问题是:
EF应该住在哪里,什么时候?
这些ORM应该被视为工作单元模式,也就是说,ORM 对象应该一直存在到业务任务完成。
在我的特定场景中,我使用像Windsor这样的IoC容器来为我完成繁重的工作。例如,在 ASP.NET MVC 应用程序中,Windsor 可以为每个 Web 请求创建一个上下文。有了这个,您不必在整个代码中编写大量语句。你可以在这里读更多关于它的内容:using
这是一个链接,直接从帮助在 Microsoft 构建框架的人那里更详细地解释它:
You can write a test application to observe the behavior of the context tracker.
If you retrieve an entity from a context, then dispose of that context, then create a new instance of the context and attempt to save a change to the entity you retrieved earlier, it will complain that it is already tracking an entity with that ID.