我正在使用WebApi 2并且需要在后台启动进程。我需要它来做它并不影响当前的请求。
所以经过一些挖掘后我发现我可以使用
public void Save(Order model) => Task.Run(() => postmanService.Update(model));
我想调试它以确保它正常工作,所以我将其更改为:
public void Save(Order model) => await postmanService.Update(model).ConfigureAwait(false);
但是当我运行这个时,我收到了这个错误:
“ObjectContext实例已被释放,不能再用于需要连接的操作。”
我不确定为什么会这样,因为我的 DatabaseContext 是这样注册的:
builder.RegisterType<DatabaseContext>().As<DbContext>().InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
builder.RegisterType<CollectionManagerProvider>().As<ICollectionManagerProvider>().InstancePerRequest();
builder.RegisterType<PostmanService>().As<IPostmanService>();
PostmanService 是将数据保存到数据库的内容,它看起来像这样:
public class PostmanService : Service<Postman>, IPostmanService
{
public PostmanService(IUnitOfWork unitOfWork) : base(unitOfWork)
{}
/// <summary>
/// Save or update a message
/// </summary>
/// <param name="model"></param>
public void Save(Postman model)
{
if (model.Id == 0)
Repository.Create(model);
else
Repository.Update(model);
}
/////////--------- Removed for brevity ---------/////////
}
存储库看起来像这样:
public class Repository<T> : IRepository<T> where T : class
{
// Create our private properties
private readonly DbContext _context;
private readonly DbSet<T> _dbEntitySet;
/// <summary>
/// Default constructor
/// </summary>
/// <param name="context">The database context</param>
public Repository(DbContext context)
{
// Assign our context and entity set
_context = context ?? throw new ArgumentNullException("context");
_dbEntitySet = context.Set<T>();
}
/// <summary>
/// Creates an entity
/// </summary>
/// <param name="model"></param>
public void Create(T model) => _dbEntitySet.Add(model);
/// <summary>
/// Updates an entity
/// </summary>
/// <param name="model"></param>
public void Update(T model) => _context.Entry<T>(model).State = EntityState.Modified;
/////////--------- Removed for brevity ---------/////////
}
最后,工作单元看起来像这样:
public class UnitOfWork : IUnitOfWork
{
private readonly Dictionary<Type, object> _repositories;
// Public properties
public DbContext Context { get; }
/// <summary>
/// Default constructor
/// </summary>
public UnitOfWork(DbContext context)
{
Context = context;
_repositories = new Dictionary<Type, object>();
}
/// <summary>
/// Gets the entity repository
/// </summary>
/// <typeparam name="TEntity">The entity model</typeparam>
/// <returns></returns>
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
// If our repositories have a matching repository, return it
if (_repositories.Keys.Contains(typeof(TEntity)))
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
// Create a new repository for our entity
var repository = new Repository<TEntity>(Context);
// Add to our list of repositories
_repositories.Add(typeof(TEntity), repository);
// Return our repository
return repository;
}
/// <summary>
/// Saves the database changes asynchronously
/// </summary>
/// <returns></returns>
public async Task SaveChangesAsync()
{
try
{
// Save the changes to the database
await Context.SaveChangesAsync();
}
catch (DbEntityValidationException ex) {
// Retrieve the error messages as a list of strings.
var errorMessages = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage);
// Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
// Combine the original exception message with the new one.
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
// Throw a new DbEntityValidationException with the improved exception message.
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
}
我不确定问题是否与 CollectionManagerProvider 以及如何注册(因为我已将其注册为 InstancePerRequest ,并且技术上该方法是针对不同的主题。
有人可以帮我这个吗?
答案 0 :(得分:0)
一种选择是使用Owned
- http://docs.autofac.org/en/latest/advanced/owned-instances.html,并自行负责处理。
public Repository(Owned<DbContext> context)
public PostmanService(Owned<IUnitOfWork> unitOfWork)
等等
或:
builder.RegisterType<DatabaseContext>().As<DbContext>().InstancePerLifetimeScope().ExternallyOwned();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope().ExternallyOwned();
等等
请参阅:
http://docs.autofac.org/en/latest/advanced/owned-instances.html http://docs.autofac.org/en/latest/lifetime/disposal.html