使用相同的数据库上下文运行多个选择查询

Posted

技术标签:

【中文标题】使用相同的数据库上下文运行多个选择查询【英文标题】:Running multiple select queries using the same db context 【发布时间】:2019-05-03 03:12:20 【问题描述】:

您能否使用相同的数据上下文运行多个“选择”查询?今天在工作中,我遇到了使用Entity Framework 4在同一上下文中运行多个“选择”查询时查询返回不准确结果的情况。代码类似于下面的代码:

            using(var dataContext = new VisitorDataContext())
            
                var v1 = dataContext.Visitor.Where(p => p.VisitorId == 73).FirstOrDefault();

//process v1
                var v2 = dataContext.Visitor.Where(p => p.VisitorId == 98).FirstOrDefault();

//process v2 
                var v3 = dataContext.Visitor.Where(p => p.VisitorId == 100).FirstOrDefault();

//provess v2
            

所以发生在我身上的是 v2 包含 v1 之前的结果。我怀疑这是因为直到这个 using 块结束时才会处理上下文。我想知道将来是否为了避免这个错误,我应该在每次查询后处理上下文。

【问题讨论】:

【参考方案1】:

DataContext 的更改跟踪器会累积您在 DataContext 的生命周期内获取的所有实体。变更跟踪器将“修复”在单独查询中获取的实体之间的关系。因此,在检查导航属性时,您可能会看到先前查询的结果。

但这不会影响您发布的代码。此外,您应该使用 EF 6,而不是 EF 4。

【讨论】:

【参考方案2】:

DbContext 会记住您已经获取的项目。这是在您保存之前能够更改获取的数据所必需的。

示例: 假设你有一所学校,有很多老师和很多学生;每个老师有零个或多个学生,每个学生有零个或多个老师(多对多关系)

假设学生 [100] 名叫 Theresa,住在“伦敦唐宁街 10 号”,她搬家了。同时,您想通知附近的所有其他学生她的新地址:

var TheresaMay = dbContext.Students.
    .Where(student => student.Id == 100)
    .FirstOrDefault();

// change address of TheresaMay:
theresaMay.Address = "King's College, Oxford",

数据尚未保存,在数据库中她仍然住在伦敦。如果你要使用这个值,你想要什么?更改后的值或数据库值:

var city = theresaMay.City; // London or Oxford?

通知附近所有学生她的新地址

var nearbyStudents = dbContext.Students
    .Where(student => student.City == theresaMay.City)
    .ToList();
SendMessage(nearbyStudents)

您希望牛津的学生收到通知,还是希望伦敦的学生收到通知?

假设您要获取按城市分组的学生:

var studentsGroupedByCitry = dbContext.Students
    .GroupBy(student => student.City)
    .ToList();

问题:Theresa 应该在伦敦学生群体中,还是在牛津学生群体中?

实体框架的设计者认为这是明智的,一旦您获取了 TheresaMay 并更改了一个属性,对于您来说,该属性的值将是新值,而不是仍在数据库中的值。

因为我们不知道您是否成功保存了更改,其他将获取 TheresaMay 的人仍然会获取数据库值。

因此,保持上下文打开以查询多个项目有点危险,因为如果其他人更改了您已经获取的项目之一,您将看不到这些更改。因此,明智的做法是只在您真正需要的时候保留您的 dbContext。通常这大约是您通常锁定数据库的时间或您保持事务活跃的时间。

【讨论】:

以上是关于使用相同的数据库上下文运行多个选择查询的主要内容,如果未能解决你的问题,请参考以下文章

什么时候适合使用 Django 上下文处理器?

servlet 上下文的多个动态数据源

React:如何使用相同类型的多个上下文,同时允许孩子从所有上下文中读取数据

如何使用相同的语句和结果集运行多个选择查询? [复制]

是否可以在 Qt 的***窗口之间使用相同的 OpenGL 上下文?

为在 Finder 中选择的多个文件禁用 NSService 上下文菜单