2017-06-15 9 views
0

私はWebApi 2を使用しており、バックグラウンドでプロセスを起動する必要があります。私はそれが何かを行うと、現在の要求に影響しないようにそれが必要です。オートファックとバックグラウンドプロセス

だから、いくつかの周りに掘った後、私はちょうど私はそれが働いていたことを確認するためにそれをデバッグしたかった

public void Save(Order model) => Task.Run(() => postmanService.Update(model)); 

使用できることがわかったので、私はこのように変更します。

public void Save(Order model) => await postmanService.Update(model).ConfigureAwait(false); 

しかし、私がこれを実行すると、私はこのエラーになります:

"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."

なぜ私は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 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 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 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 としてそれを登録しているとtechinically方法は、別のスレッドで解雇されているので、どのようにそれが(登録されています。

誰かがこれを手伝ってくれますか?

+0

一つのオプションは 'Owned'を使うことです - http://docs.autofac.org/en/latest/advanced/owned-instances.htmlそしてそれを自分で掃除する責任を負います。 – mjwills

+0

私はそれについて考えました。あなたは私に例を与えることができますか、それはどのように見えるかもしれませんか? – r3plica

+0

'Owned 'を使っているように見えるのは答えです。私はちょうど今いくつかのテストをしています – r3plica

答えて

0

1つのオプションは、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>().Inst‌​ancePerLifetimeScope‌​().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

+0

外部所有のインスタンスが働いていました。理由は分かりませんが、私は満足しています:D – r3plica

+0

それはあなたがそれを支配して以来、基本的に動作します。 async/awaitを使用すると、ライフタイムスコープは予想よりも早く終了します。これは、Web要求の全期間中オープンされていないためです。 '所有している'を使うことで、あなたは「心配しないで、私はDisposeを呼び出します。したがって、コンテナはDisposeを呼び出さないため、エラーは消えます。 – mjwills

+0

私はOwnedを使用していません。ただ '.ExternallyOwned'です。それは重要ですか? – r3plica

関連する問題