实体框架读取锁定所有数据库的查询

时间:2016-07-25 19:33:04

标签: c# asp.net-mvc database entity-framework entity-framework-6

我正在使用ASP.NET MVC和EF6开发一个Web应用程序来访问数据库。

我的网络应用程序的一项功能允许用户下载Excel文件。从数据库中获取信息的查询需要5秒钟,我注意到在查询完成之前,我们无法对其余的Web应用程序执行任何操作。

这是EF的正常行为,即使查询中有AsNoTracking,也会锁定数据库?

如果我没有做错任何事情,这是EF的默认行为,我应该如何解决这个锁定问题?

(更新)

我使用的是SQL Server数据库和" lock"例如,当我导出excel文件并同时进行使用相同表的搜索时,就会发生这种情况。

使用Repository和UnitOfWork模式组织我的代码,并使用DI Unity创建实例。

UnitOfWork实施:

public class UnitOfWork : IUnitOfWork
{

    private bool _disposed;
    private DbContext _dbContext;
    private Dictionary<string, dynamic> _repositories;
    private DbContextTransaction _transaction;

    public DbContext DbContext
    {
        get { return _dbContext; }
    }

    public UnitOfWork(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public int SaveChanges()
    {
        return _dbContext.SaveChanges();
    }

    public IRepository<TEntity> Repository<TEntity>()
    {   
        try
        {
            if (ServiceLocator.IsLocationProviderSet)
                return ServiceLocator.Current.GetInstance<IRepository<TEntity>>();

            if (_repositories == null)
                _repositories = new Dictionary<string, dynamic>();

            var type = typeof(TEntity).Name;

            if (_repositories.ContainsKey(type))
                return (IRepositoryAsync<TEntity>)_repositories[type];

            var repositoryType = typeof(Repository<>);

            _repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof(TEntity)), this));

            return _repositories[type];
        }
        catch(ActivationException ex)
        {
            throw new ActivationException(string.Format("You need to configure the implementation of the IRepository<{0}> interface.", typeof(TEntity)), ex);
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~UnitOfWork()
    {
        Dispose(false);
    }

    public void Dispose(bool disposing)
    {
        if(!_disposed)
        {
            if(disposing)
            {
                try
                {
                    _dbContext.Dispose();
                    _dbContext = null;
                }
                catch(ObjectDisposedException)
                {
                    //the object has already be disposed
                }
                _disposed = true;
            }
        }
    }
}

存储库实现:

public class Repository<TEntity> : IRepository<TEntity>
        where TEntity : class
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly DbContext _dbContext;
    private readonly DbSet<TEntity> _dbSet;

    public Repository(IUnitOfWork unitOfWork)
    {

        _unitOfWork = unitOfWork;
        _dbContext = unitOfWork.DbContext;
        _dbSet = _dbContext.Set<TEntity>();
    }

    #region IRepository<TEntity> implementation

    public void Insert(TEntity entity)
    {
        _dbSet.Add(entity);
    }

    public void Update(TEntity entity)
    {
        _dbContext.Entry(entity).State = EntityState.Modified;
    }

    public void Delete(TEntity entity)
    {
        _dbSet.Remove(entity);
    }

    public IQueryable<TEntity> Queryable()
    {
        return _dbSet;
    }

    public IRepository<TEntity> GetRepository<TEntity>()
    {
        return _unitOfWork.Repository<TEntity>();
    }

    #endregion

}

Unity配置:

    container.RegisterType<DbContext, DbSittiusContext>(new PerRequestLifetimeManager());
    container.RegisterType<IUnitOfWork, UnitOfWork>(new PerRequestLifetimeManager());

    //Catalog respository register types
    container.RegisterType<IRepository<Product>, Repository<Product>>();

    UnityServiceLocator locator = new UnityServiceLocator(container);
    ServiceLocator.SetLocatorProvider(() => locator);

要创建我的查询,必须创建一个这样的扩展方法:

public static Product FindPublishedAtDateById(this IRepository<Product> repository, int id, DateTime date)
{
    return repository.
            Queryable().
            Where(p => p.Id == id).
            Where(p => p.PublishedFrom <= date && (p.PublishedTo == null || p.PublishedTo >= date)).
            SingleOrDefault();
}

1 个答案:

答案 0 :(得分:0)

如果您同步下载大量数据,则会使用户界面冻结。考虑异步执行此操作。无论如何,你在使用客户端是什么?

我假设您正在从数据库中的数据生成excel文件,而这只是一个足够的数据,创建文件并将其发送给用户需要大约5秒钟。