EF5 / Base Repository的并发问题

时间:2012-11-05 13:00:39

标签: c# entity-framework

我已经完成了一个新应用程序的编写,该应用程序现已部署到实时环境中,但是我的全局错误处理程序在一整天内多次拾取这些异常。这些错误分批进行,是粗体中的四个之一。

MVC 4,IIS 6,Windows Server 2003,.Net .4.0,EF 5(最新版NuGet)

“ARandomModelInMyContext”类型已多次映射。

指数超出范围。必须是非负数且小于集合的大小。

Parameter name: index
System.ThrowHelper.ThrowArgumentOutOfRangeException() at System.Data.Metadata.Edm.MetadataCollection`1.get_Item(Int32 index) at System.Data.Mapping.DefaultObjectMappingItemCollection.ContainsMap(GlobalItem cspaceItem, ObjectTypeMapping& map) at

创建模型时无法使用上下文。

System.Data.Entity.Internal.LazyInternalContext.InitializeContext() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()

基础提供程序在Open上失败。连接没有关闭。连接的当前状态是连接。

应用程序的结构是一个非常标准的MVC4应用程序,它带有服务层和存储库层。

  • 服务在构造函数中创建一个repo
  • Repository在存储库构造函数中创建一个新的Context,如下所示:

public class MyRepository : BaseRepository<MyModel>, IMyRepository

使用构造函数:

public MyRepository() : base(new MyEntities())
{
}

Base Repository看起来像这样:

public class BaseRepository<TEntity> where TEntity : class
{
    internal CRMEntities Context;
    internal DbSet<TEntity> dbSet;
    public BaseRepository(MyEntities context)
    {
        this.Context = context;
        dbSet = context.Set<TEntity>();
    }
}

不应该有任何并发​​问题,因为我没有直接使用任何线程或异步。

有什么想法吗?我的存储库结构可以改进吗?我已经让所有的构造函数都可以了,但是我还没有使用IoC容器。

将Context中的Context构造包装起来是否值得?例如:

public class BaseRepository<TEntity> where TEntity : class
{
    internal MyEntities Context;
    internal DbSet<TEntity> dbSet;
    private static object _lock = new object();

    public BaseRepository(MyEntities context)
    {
        lock (_lock)
        {
            this.Context = context;
            dbSet = context.Set<TEntity>();
        }
    }
 }

1 个答案:

答案 0 :(得分:1)

它看起来非常像您的存储库(因此您的上下文)被多个请求使用。如果这是真的,那么这是多线程使用相同的上下文实例,这是不受支持的 - 上下文不是线程安全的。仅锁定初始化是不够的。 (另外,调用Set不会初始化上下文。)您需要保护对上下文的所有访问,或者更恰当地使用具有短期上下文实例的每个请求模型的上下文。