我正在使用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();
}
答案 0 :(得分:0)
如果您同步下载大量数据,则会使用户界面冻结。考虑异步执行此操作。无论如何,你在使用客户端是什么?
我假设您正在从数据库中的数据生成excel文件,而这只是一个足够的数据,创建文件并将其发送给用户需要大约5秒钟。