У меня есть веб-служба WCF, которая в настоящее время сталкивается с некоторыми проблемами параллелизма. На данный момент нагрузка небольшая, но ожидается, что в ближайшие несколько дней она увеличится.Операция не может быть завершена, потому что DbContext был удален - LifestylePerWcfOperation
Общая настройка WCF, Entity Framework 6, Injection Dependency (Castle Windsor), UnitOfWork & Образцовый шаблон.
я настроить стресс-тест, который попадает на службу параллельно, и я могу воссоздать ошибки параллелизма, такие как ....
- сообщалось ошибка при совершении транзакции базы данных, но он не может определить, являются ли транзакция выполнена успешно или сбой на сервере базы данных.
Изменения в базе данных были успешно завершены, но при обновлении контекста объекта произошла ошибка. Объект ObjectContext может находиться в несогласованном состоянии. Внутреннее сообщение об исключении: AcceptChanges не может продолжаться, потому что ключевые значения объекта конфликтуют с другим объектом в ObjectStateManager. Перед вызовом AcceptChanges убедитесь, что значения ключа уникальны.
Идентификатор объекта 'property' является частью ключевой информации объекта и не может быть изменен.
Из исследования я сделал, это выглядит, как я должен инъекционным мой DbContext с LifestylePerWcfOperation. В настоящее время это делается с LifestyleTransient.
Когда я перейти на LifestylePerWcfOperation и повторите тест, я получаю это каждый раз, когда:
- Операция не может быть завершена, поскольку DbContext были захоронены
Так что я на самом деле есть 2 вопроса :
- Я исхожу в предположении, что истинное решение этого вопроса заключается в переключении моего DbContext на LifestylePerWcfOperation?
- Если да, то понятно, почему мой DbContext получает ворс?
Вот код:
AppStart.cs:
IocContainer.AddFacility<TypedFactoryFacility>();
IocContainer.Register(Component.For<IRepositoryFactory>().AsFactory());
IocContainer.Register(Component.For<IUnitOfWork>()
.ImplementedBy<UnitOfWork>)
/*.LifestylePerWcfOperation()*/);
IocContainer.Register(Component.For(typeof(IDbContext))
.ImplementedBy(dbContextType)
.DependsOn(Dependency.OnValue("connectionString", String.Format(ConfigurationManager.ConnectionStrings["---"].ConnectionString))));
/*.LifestylePerWcfOperation()*/
IocContainer.Register(Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(Repository<>))
.LifestyleTransient()
/*.LifestylePerWcfOperation()*/);
// Register the actual dbContextType so consuming applications can access it without an interface
IocContainer.Register(Component.For(dbContextType)
.Named(dbContextType.Name)
.DependsOn(Dependency.OnValue("connectionString", String.Format(ConfigurationManager.ConnectionStrings["----"].ConnectionString)));
/*.LifestylePerWcfOperation()*/
UnitOfWork.cs:
public class UnitOfWork : IUnitOfWork
{
private readonly IDbContext _dbContext;
private bool _disposed;
public UnitOfWork(IDbContext dbContext)
{
_dbContext = dbContext;
}
public int Commit()
{
return _dbContext.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_dbContext.Dispose();
}
_disposed = true;
}
}
}
Repository.cs
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbSet<T> _dbset;
public Repository(IDbContext dbContext)
{
_dbset = dbContext.Set<T>();
}
public IQueryable<T> Query()
{
return _dbset.AsQueryable();
}
public virtual IEnumerable<T> GetAll()
{
return _dbset.AsEnumerable();
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
_dbset.Remove(entity);
}
public virtual void Delete(ICollection<T> entities)
{
entities.ToList().ForEach(Delete);
}
}
При необходимости я могу добавить дополнительный код. Спасибо за любую помощь, которую вы можете предоставить!
В вашей регистрации DBContext не указывается стиль жизни, поэтому применяется значение Windsor по умолчанию: Singleton. Это, безусловно, вызовет проблемы. –