简体   繁体   English

EF5 /基本存储库的并发问题

[英]Concurrency issues with EF5 / Base Repository

I've finished writing a new application which has now been deployed into the live environment however my global error handler is picking up these exceptions several times throughout the day. 我已经完成了一个新的应用程序的编写,该应用程序现在已经部署到了实时环境中,但是我的全局错误处理程序整天几次都在处理这些异常。 These errors come in batches and are one of the four in bold. 这些错误是成批出现的,是四个粗体错误之一。

MVC 4, IIS 6, Windows Server 2003, .Net .4.0, EF 5 (latest from NuGet) MVC 4,IIS 6,Windows Server 2003,.Net .4.0,EF 5(来自NuGet的最新版本)

The type 'ARandomModelInMyContext' has been mapped more than once. 类型“ ARandomModelInMyContext”已被映射多次。

Index was out of range. 索引超出范围。 Must be non-negative and less than the size of the collection. 必须为非负数并且小于集合的大小。

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

The context cannot be used while the model is being created. 创建模型时不能使用上下文。

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

The underlying provider failed on Open. 基础提供程序在打开时失败。 The connection was not closed. 连接未关闭。 The connection's current state is connecting. 连接的当前状态为连接中。

The structure of the application is a pretty standard MVC4 application with a Service Layer and a repository layer. 该应用程序的结构是带有服务层和存储库层的标准MVC4应用程序。

  • A service creates a repo in the constructor 服务在构造函数中创建一个仓库
  • Repository creates a new Context in the repository constructor like so: 仓库在仓库构造函数中创建一个新的上下文,如下所示:

public class MyRepository : BaseRepository<MyModel>, IMyRepository

With the constructor: 使用构造函数:

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

Base Repository looks like this: 基本存储库如下所示:

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>();
    }
}

There shouldn't be any concurrency issues as I'm not making directly using any threading or async. 不应有任何并发​​问题,因为我不是直接使用任何线程或异步进行的。

Any ideas? 有任何想法吗? Can my repository structure be improved? 我的存储库结构可以改善吗? I've made all the constructors DI-able however I'm not using an IoC container yet. 我已经使所有构造函数都具有DI功能,但是我还没有使用IoC容器。

Would wrapping the construction of the Context in the repository in lock be worth while? 将Context的构造封装在存储库中是否值得? For example: 例如:

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>();
        }
    }
 }

It looks very much like your Repository (and hence your context) is used by multiple requests. 它看起来非常像您的存储库(以及您的上下文)被多个请求使用。 if this is true, then this is multi-threaded use of the same context instance, which is not supported--the context is not thread-safe. 如果为真,则这是对同一上下文实例的多线程使用,不支持该上下文实例-上下文不是线程安全的。 Locking just the initialization is not sufficient. 仅锁定初始化是不够的。 (Also, calling Set does not initialize the context.) You would need to protect all access to the context, or more appropriately use a context per request model with short-lived context instances. (此外,调用Set不会初始化上下文。)您将需要保护对上下文的所有访问,或者更适当地将每个请求模型的上下文与短暂的上下文实例一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM