我正在.net Web Api应用程序中使用Ef6。 这是一个遗留的整体,我们正在尝试将其转换为微服务CQRS架构。当前,我们在使用EF6时遇到了并发问题,我不知道如何进行分类。 首先,我有两个数据库(写和读)。我们正在使用SQL Server 2012作为RDBMS。我正在将IOC / DI与Autofac一起使用,并且由于我们有2个数据库,所以我想创建2个不同的上下文对象,这就是代码的样子。
//工作单元构造器
public UnitOfWork(IContext readContext, IContext writeContext, IMapper
mapper)
{
_readContext = readContext;
_writeContext = writeContext;
_mapper = mapper; //this is for the automapper
}
这将从IContext接口创建2个上下文对象。
// IContext接口具有以下两个自定义上下文对象
public partial class MyWriteContext : IContext,IDisposable
{
}
public partial class MyReadContext : IContext,IDisposable
{
}
我们已经故意创建了这两个类,因为这两个名称与我们用来创建实际Ef6 dbcontext的名称相同
//由反向poco生成的实际实体框架上下文对象
public partial class EfWriteContext : DbContext{}
partial class EFReadContext : DbContext{}
这是我的Autofac配置,用于相同的dbcontext,工作单元和通用存储库,这些配置都在autofac模块中定义并在Web API Startup.cs中注册和解析
//上下文自动注册模块
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<MyReadContext>()
.Named<IContext>("MyReadContext")
.InstancePerDependency();
builder.RegisterType<MyWriteContext>()
.Named<IContext>("MyWriteContext")
.InstancePerDependency();
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing -= Registration_Preparing;
registration.Preparing += Registration_Preparing;
}
private void Registration_Preparing(object sender, PreparingEventArgs e)
{
Parameter parameter = new ResolvedParameter(
(pi, c) => pi.ParameterType == typeof(IContext),
(pi, c) =>
{
if (pi.Name.Equals("readContext", StringComparison.OrdinalIgnoreCase))
{
return c.ResolveNamed<IContext>("MyReadContext");
}
else if (pi.Name.Equals("writeContext", StringComparison.OrdinalIgnoreCase))
{
return c.ResolveNamed<IContext>("MyWriteContext");
}
else
{
return c.ResolveNamed<IContext>("MyReadContext");
}
});
e.Parameters = e.Parameters.Concat(new Parameter[] { parameter });
}
//工作单元
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerDependency();
//存储库
builder.RegisterAssemblyTypes(Assembly.Load("Infrastructure"))
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.InstancePerDependency();
//存储库构造器
public Repository(IContext dbContext)
{
context = dbContext;
_dbset = context.Set<TEntity>();
}
在调用writecontext.SaveChanges()的情况下,此代码可以完美地工作并在单个用户的情况下插入和更新数据。如果在数据库中保存数据时多个用户之间有时间间隔,它甚至可以工作,但是当2个用户实际上试图同时在数据库中保存数据时,就会出现问题。然后开始抛出错误
参数'entitySetName'不能为null,为空或仅包含空格。
模型中已经存在项目。
违反PRIMARY KEY约束。无法在对象中插入重复的密钥。重复的键值为(0,4862)。该声明已终止。
,随后所有用户的调用也开始失败。