实体框架 创建模型时无法使用上下文
Posted
技术标签:
【中文标题】实体框架 创建模型时无法使用上下文【英文标题】:Entity Framework The context cannot be used while the model is being created 【发布时间】:2016-01-13 18:17:44 【问题描述】:下面提到了我的工作单元类,我正在使用 Ninject,我尝试为每个线程范围、瞬态等的每个请求注入 IUnitOfWork
,但我仍然收到错误消息:
"Message":"发生错误。","ExceptionMessage":"创建模型时无法使用上下文。如果在 OnModelCreating 方法内部使用上下文或相同的上下文,则可能会引发此异常context 实例被多个线程并发访问。注意,DbContext 和相关类的实例成员不保证是线程安全的。","ExceptionType":"System.InvalidOperationException
当我使用 angularJS 同时进行两个 Web API (get) 调用时出现此错误,它在_context.Set<TEntity>().FirstOrDefault(match);
处显示错误
public class UnitOfWork : IUnitOfWork, IDisposable
private My_PromotoolEntities _uowDbContext = new My_PromotoolEntities();
private Dictionary<string, object> _repositories;
// Do it like this if no specific class file
private GenericRepository<MysPerson> _personRepository;
//private GenericRepository<MysDataSource> dataSourcesRepository;
//private GenericRepository<MysCountry> countryMasterRepository;
// Or like this if with specific class file.
private DataSourceRepository _dataSourcesRepository;
private CustomerRepository _customerRepository;
private DeviceRepository _deviceRepository;
private DeviceRegistrationRepository _deviceRegistrationRepository;
private EmailQueueRepository _emailQueueRepository;
public void SetContext(My_PromotoolEntities context)
_uowDbContext = context;
public void CacheThis(object cacheThis, string keyName, TimeSpan howLong)
Cacheing.StaticData.CacheStaticData(cacheThis, keyName, howLong);
public object GetFromCache(string keyName)
return Cacheing.StaticData.GetFromCache(keyName);
public GenericRepository<T> GenericRepository<T>() where T : BaseEntity
if (_repositories == null)
_repositories = new Dictionary<string, object>();
var type = typeof(T).Name;
if (!_repositories.ContainsKey(type))
var repositoryType = typeof(GenericRepository<>);
var repositoryInstance = Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)), _uowDbContext);
_repositories.Add(type, repositoryInstance);
return (GenericRepository<T>)_repositories[type];
public GenericRepository<MysPerson> PersonRepository
get
if (this._personRepository == null)
this._personRepository = new GenericRepository<MysPerson>(_uowDbContext);
return _personRepository;
public DataSourceRepository DataSourcesRepository
get
if (this._dataSourcesRepository == null)
this._dataSourcesRepository = new DataSourceRepository(_uowDbContext);
return _dataSourcesRepository;
public CustomerRepository CustomerRepository
get
if (this._customerRepository == null)
this._customerRepository = new CustomerRepository(_uowDbContext);
return _customerRepository;
public DeviceRepository DeviceRepository
get
if (this._deviceRepository == null)
this._deviceRepository = new DeviceRepository(_uowDbContext);
return _deviceRepository;
public DeviceRegistrationRepository DeviceRegistrationRepository
get
if (this._deviceRegistrationRepository == null)
this._deviceRegistrationRepository = new DeviceRegistrationRepository(_uowDbContext);
return _deviceRegistrationRepository;
public EmailQueueRepository emailQueueRepository
get
if (this._emailQueueRepository == null)
this._emailQueueRepository = new EmailQueueRepository(_uowDbContext);
return _emailQueueRepository;
/// <summary>
/// Commits all changes to the db. Throws exception if fails. Call should be in a try..catch.
/// </summary>
public void Save()
try
_uowDbContext.SaveChanges();
catch (DbEntityValidationException dbevex)
// Entity Framework specific errors:
StringBuilder sb = new StringBuilder();
var eve = GetValidationErrors();
if (eve.Count() > 0)
eve.ForEach(error => sb.AppendLine(error));
ClearContext();
// Throw a new exception with original as inner.
var ex = new Exception(sb.ToString(), dbevex);
ex.Source = "DbEntityValidationException";
throw ex;
catch (Exception)
ClearContext();
throw;
private void ClearContext()
DetachAll();
private void DetachAll()
foreach (DbEntityEntry dbEntityEntry in _uowDbContext.ChangeTracker.Entries())
if (dbEntityEntry.Entity != null)
dbEntityEntry.State = EntityState.Detached;
/// <summary>
/// Checks for EF DbEntityValidationException(s).
/// </summary>
/// <returns>Returns a List of string containing the EF DbEntityValidationException(s).</returns>
public List<string> GetValidationErrors()
if (_uowDbContext.GetValidationErrors().Count() != 0)
return _uowDbContext.GetValidationErrors().Select(e => string.Join(Environment.NewLine, e.ValidationErrors.Select(v => string.Format("0 - 1", v.PropertyName, v.ErrorMessage)))).ToList();
return null;
private bool disposed = false;
protected virtual void Dispose(bool disposing)
if (!this.disposed)
if (disposing)
_uowDbContext.Dispose();
this.disposed = true;
public void Dispose()
Dispose(true);
GC.SuppressFinalize(this);
【问题讨论】:
【参考方案1】:您不应该同时在 2 个地方使用上下文,这正是您收到此错误的原因。来自MSDN documentation:
线程安全:这种类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。 不保证任何实例成员都是线程安全的。
【讨论】:
谢谢你能解释一下我是如何在两个地方使用上下文的 无法从这段代码中看出,我猜你正在注入IUnitOfWork
的共享副本。
我已经搜索了我的所有代码,唯一能找到参考的地方是 ninjectWebCommon,即 kernel.Bind在没有复制的情况下提出建议有点困难,但有一种蛮力方法可以解决问题。如果您在 DI 设置之前/期间有一个拦截点,那么您可以通过创建上下文实例并调用 ctx.Database.Initialize(force: false); 来导致所有上下文初始化等发生。传递 'force: false' 将确保每个 AppDomain 仍然只发生一次初始化
【讨论】:
以上是关于实体框架 创建模型时无法使用上下文的主要内容,如果未能解决你的问题,请参考以下文章
无法为“ApplicationUser”创建 DbSet,因为此类型未包含在上下文模型中