entity framework异步发出上下文或查询?

我的下面的查询有异步问题。 我有单例上下文,我试图执行以下查询:

var query = await (from parent in Context.ParentTable join child in Context.ChildTable on parent.ID equals child.ID into allResult from ResultValue in allResult.DefaultIfEmpty() where ResultValue.TenantId == tenantId select new Result { Code = parent.Code, Type = parent.Type, ID = ResultValue == null ? 0 : ResultValue.Id }).ToListAsync(); 

我的单例上下文如下所示:

 public class BaseRepository { private readonly IConfigurationContextFactory configurationContextFactory; private IConfigurationContext context; protected IConfigurationContext Context { get { return context ?? (context = configurationContextFactory.Context); } } public BaseRepository(IConfigurationContextFactory configurationContextFactory) { this.configurationContextFactory = configurationContextFactory; } } 

配置上下文工厂返回Context,如下所示:

 private ConfigurationContext Get() { logger.WriteEntrySync(LogLevel.Information, null != context ? "Config Context: Using existing context." : "Config Context: Wiil create new context."); return context ?? (context = new ConfigurationContext(connectionString)); } 

在这个我得到以下错误的间歇性问题:

在先前的异步操作完成之前,在该上下文上开始第二个操作。 使用’await’确保在此上下文上调用另一个方法之前已完成任何异步操作。 任何实例成员都不保证是线程安全的。

我有单身语境

这是你的问题。 DbContext不是线程安全的,旨在一次执行一个查询。 由于您正在共享DbContext ,因此您可能正在尝试同时调用另一个查询,这在DbContext术语中并非“合法”。

您甚至可以在ToListAsync的备注中看到它:

不支持在同一上下文实例上进行多个活动操作。 使用’await’确保在此上下文上调用另一个方法之前已完成任何异步操作。

应该做的不是通过全局单例重用您的上下文,每次要查询数据库时都创建一个新的上下文。

编辑:

不是通过工厂方法获取单个Context ,只需为每个查询分配一个新的:

 using (var context = new ConfigurationContext(connectionString)) { var query = await (from feature in context.Features join featureFlag in context.FeatureFlags on feature.FeatureId equals featureFlag.FeatureId into allFeatures from featureFlagValue in allFeatures.DefaultIfEmpty() where featureFlagValue.TenantId == tenantId select new BusinessEntities.FeatureFlag { Code = feature.Code, Type = feature.Type, FeatureFlagId = featureFlagValue == null ? 0 : featureFlagValue.FeatureFlagId }).ToListAsync(); } 

DbContext应该适用于一个业务事务(工作单元),不多也不少。 业务事务通常是请求,页面或表单。 DbContext不是线程安全的,它保留一个内部实体缓存并跟踪更改,因此您无法在多个请求中共享它。

您真的需要阅读entity framework文档: 使用DbContext 。

我不会为每个存储库创建一个实例,因为业务事务可以操作多个存储库。

您可以在存储库中注入上下文:

 public class BaseRepository { private IConfigurationContext context; public BaseRepository(IConfigurationContext context) { this.context = context; } //... } 

更改工厂,以便每次都创建一个实例:

 public interface IConfigurationContextFactory { IConfigurationContext CreateContext(); } // ... public ConfigurationContext CreateContext() { return new ConfigurationContext(connectionString); } 

然后配置依赖项解析程序以在每个工作单元中注入IConfigurationContext 。 假设您正在使用unity实现ASP.NET应用程序。

 container.RegisterType( //Instance per http request (unit of work) new PerRequestLifetimeManager(), //Create using factory new InjectionFactory(c => c.Resolve.CreateContext())); 

不要忘记在需要时在业务事务结束时调用SaveChangesAsync :操作成功并且需要保留修改。