在同一次提交中执行两个First()

时间:2017-08-13 10:11:34

标签: c# entity-framework

我有First()的两个查询,在检测FirstToList等方法时,EF总是针对数据库执行查询。

我的提交包括检查是否存在新的,然后检查用户是否已投票。

int theId = 33;

// Check if the new exists
var theNew =
    await this.context
        .News
        .FirstAsync(x => x.Id == theId);

// The new doesn't exist
if (theNew == null)
{
    return NotFound();
}

// Check if the user has voted the new
var voted =
    await this.context
        .UserVoteNews
        .FirstAsync(x => x.UserId == this.UserId && x.NewId == theId);

if (voted == null)
{
    return BadRequest(@"User didn't vote");
}
else
{
    return Ok("User voted");
}

我已经尝试了

using (var dbContextTransaction = this.context.Database.BeginTransaction())

但服务器在此之前使用FirstAsync执行查询

await this.context.SaveChangesAsync();
dbContextTransaction.Commit();

3 个答案:

答案 0 :(得分:1)

首先,我认为你误解了交易的目的。 (主要)用于修改数据库的事务。如果您只想读取所有内容,那么通常无需担心提交等等。

其次,在使用EF时,除了非常具体的用例外,您无需在所有中使用事务。你可以这样做:

using (var context = new Context())
{
    // Stuff
    context.SaveChanges();
}

我可以从你的例子中看出你有this.context,你可能在整个班级中使用using。推荐的方法是没有单个上下文,但在需要时创建一个新上下文,就像我刚刚展示的示例一样。这使您可以有效地使用EF的实体跟踪,从而无需使用事务。

SaveChanges块中,您可以执行涉及上下文,读取和写入的任何(有效)操作。 EF会跟踪任何和所有更改,并在您致电SaveChanges时提交。当您致电using (var context = new Context()) // Create a new context for this { int theId = 33; var theNew = await context.News.FirstAsync(x => x.Id == theId); if (theNew != null) { var voted = await context.UserVoteNews.FirstAsync(x => x.UserId == this.UserId && x.NewId == theId); // Returns are mutually exclusive so clean up by removing else clauses if (voted != null) { return Ok("User voted"); } return BadRequest(@"User didn't vote"); } return NotFound(); } 时,不会执行读取查询,而是在转换后立即将其发送给提供商。

以下是您的代码的修订版本:

SaveChanges

请注意,我从不致电SaveChangesAsync@Component({ selector: "page-job-details", templateUrl: "job-details.html", animations: [ trigger('expand', [ state('ActiveGroup', style({opacity: '1', height: '*'})), state('NotActiveGroup', style({opacity: '0', height: '0', overflow: 'hidden'})), transition('ActiveGroup <=> NotActiveGroup', animate('300ms ease-in-out')) ]) ] }) ionViewDidLoad() { this.items = [ {title: 'First Button', data: 'First-content', activeGroup: 'NotActiveGroup'}, {title: 'Second Button', data: 'Second-content', activeGroup: 'NotActiveGroup'}, {title: 'Third Button', data: 'Third-content', activeGroup: 'NotActiveGroup'} ]; } expandItem(item){ this.items.map(listItem => { if (item == listItem){ listItem.activeGroup = listItem.activeGroup === 'ActiveGroup' ? 'NotActiveGroup' : 'ActiveGroup'; } return listItem; }); } ,因为我们没有修改任何内容。

答案 1 :(得分:1)

仅使用实体框架就无法实现这种行为。

但是,某些第三方库允许这样做。

免责声明:我是该项目的所有者Entity Framework Plus

此库允许您Defer查询Immediate此类First方法。

该库还允许您通过Future功能批量处理多个查询。因此,所有挂起的查询都在相同的commit或数据库往返中执行。

var theNewDeferred = context.News.DeferredFirst(x => x.Id == theId).FutureValue();
var votedDeferred = context.UserVoteNews.DeferredFirst(x => x.UserId == this.UserId && x.NewId == theId).FutureValue();

// Both FutureValue will be executed in the same database round-trip
var theNew = await theNewDeferred.ValueAsync();

if(theNew != null)
{
}

答案 2 :(得分:0)

要么我不了解你,要么你不理解EF。一旦查询生效,读取操作将立即发送到数据库,例如通过调用FirstAsync。您似乎认为只要您调用SaveChangesAsyncCommit,就会执行读取查询。 SaveChangesAsync将在数据库上启动写入操作。像INSERT,DELETE和UPDATE一样。