2016-08-23 64 views
1

我利用EF 6的能力来将Enum的属性用作实体对象。实体框架6 Async DBContext使用枚举访问

当我尝试使用此枚举属性作为条件的一部分异步查询数据源时,查询从不返回。但是,如果我同步查询,它会成功完成。 EF生成的SQL对于这两种情况都是相同的,并且是正确的。

这里的简化版本我entity object的:

public class RoleGroup { 
    public int Id { get; set; } 

    [Column("RequestSubTypeId")] 
    public SubTypeEnum? SubTypeId { get; set; } 
} 

这里是我的enum的简化版本:

public enum SubTypeEnum { 
    AccountsPayableInquiry = 1, 
    PayrollInquiry = 2, 
    BillingInquiry = 3 
} 

这里的我使用从数据库中检索角色组的method,基于subTypeId参数:

public async Task<RoleGroup> GetRoleGroupBySubType(SubTypeEnum subTypeId) { 
    return await Context.WorkflowRoleGroups 
         .FirstAsync(roleGroup => roleGroup.SubTypeId == subTypeId); 
} 

使用Context.Database.Log = s => Debug.WriteLine(s);我能看到下面的SQL是通过上述方法生产:

SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[RequestSubTypeId] AS [RequestSubTypeId] 
FROM [dbo].[WorkflowRoleGroups] AS [Extent1] 
WHERE [Extent1].[RequestSubTypeId] = @p__linq__0 

-- p__linq__0: '1' (Type = Int32, IsNullable = false) 

然而,这只要执行得到。没有任何反应,没有错误发生。在输出窗口中,我看到“线程已退出代码0”。

当我让方法同步时,就像下面的例子一样,从数据库返回正确的结果,一切都很好。生成的SQL查询与异步查询完全相同。

public RoleGroup GetRoleGroupBySubType(SubTypeEnum subTypeId) { 
    return Context.WorkflowRoleGroups 
        .First(roleGroup => roleGroup.SubTypeId == subTypeId); 
} 

我会很感激的,为什么在使用异步与enum作为标准的一部分了解任何指导会导致此问题。

+0

它可能与EF没有任何关系,但与使用async/await和在调用堆栈中使用类似'Task.Result'(*会引起死锁*)的东西有关。整个调用堆栈应该在每个点都使用async/await(也称为async一路)。没有看到调用堆栈中的所有其他代码,都无法知道哪个部分导致了死锁。 – Igor

+0

非常有趣。你已经死了。调用它的同步方法最后有'.Result'。我通过在Task.Run(async()=> await GetRoleGroupBySubType(subTypeId))中包装了整个async方法调用做了一个快速测试。Result'和它的工作没有问题。我想更多地了解为什么'.Result'会导致死锁,但是'Task.Run()。Result'不会。你偶然知道更多信息的好来源吗?附:让你的评论成为答案,我会接受。 – Sam

回答

2

它可能与EF没有任何关系,但与使用async/await和将它与Task.Result(这会导致死锁)在调用堆栈中混合使用有关。整个调用堆栈应该在每个点都使用async/await(也称为async一路)。没有看到调用堆栈中的所有其他代码,都无法知道哪个部分导致了死锁。

这里是理解为什么/如何发生死锁Don't Block on Async Code的好资料。 Stephen Cleary(所引用文章的作者)通常也会回应关于SO的异步等待问题。

+1

太棒了 - 谢谢伊戈尔! – Sam