Rus*_*sty 6 c# asynchronous entity-framework async-await
我的下面的查询有异步问题.我有单例上下文,我试图执行以下查询:
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();
Run Code Online (Sandbox Code Playgroud)
我的单例上下文如下所示:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
配置上下文工厂返回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));
}
Run Code Online (Sandbox Code Playgroud)
在此我得到以下错误的间歇性问题:
在先前的异步操作完成之前,在该上下文上开始第二操作.使用'await'确保在此上下文上调用另一个方法之前已完成任何异步操作.任何实例成员都不保证是线程安全的.
Yuv*_*kov 21
我有单身语境
这是你的问题.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();
}
Run Code Online (Sandbox Code Playgroud)
A DbContext
应该适用于一项商业交易(工作单位),不能少于此.业务事务通常是请求,页面或表单.DbContext不是线程安全的,它保留一个内部实体缓存并跟踪更改,因此您无法在多个请求中共享它.
您真的需要阅读实体框架文档:使用DbContext.
我不会为每个存储库创建一个实例,因为业务事务可以操作多个存储库.
您可以在存储库中注入上下文:
public class BaseRepository
{
private IConfigurationContext context;
public BaseRepository(IConfigurationContext context)
{
this.context = context;
}
//...
}
Run Code Online (Sandbox Code Playgroud)
更改工厂,以便每次都创建一个实例:
public interface IConfigurationContextFactory
{
IConfigurationContext CreateContext();
}
// ...
public ConfigurationContext CreateContext()
{
return new ConfigurationContext(connectionString);
}
Run Code Online (Sandbox Code Playgroud)
然后配置依赖项解析程序以注入IConfigurationContext
每个单元的工作.假设您正在使用统一的ASP.NET应用程序.
container.RegisterType<IConfigurationContext>(
//Instance per http request (unit of work)
new PerRequestLifetimeManager(),
//Create using factory
new InjectionFactory(c => c.Resolve<IConfigurationContextFactory>.CreateContext()));
Run Code Online (Sandbox Code Playgroud)
不要忘记在需要SaveChangesAsync
时在业务事务结束时调用:操作成功并且需要保持修改.
归档时间: |
|
查看次数: |
16271 次 |
最近记录: |