连续运行Azure WebJob的新DBContext

时间:2017-08-29 01:57:45

标签: autofac dbcontext azure-webjobs

我正在连续运行Azure WebJob,它正在我的数据库中执行CRUD操作。我正在使用Entity Framework和UnitOfWork模式,在我的WebJob中,我使用Autofac来注入我的依赖项,服务和存储库层。运行我的WebJob时,我遇到了一些陈旧数据的问题。

实施例: 我在我的网站上更新了一条记录,然后我的WebJob被启动,但我的WebJob无法在数据库中看到此更改。它会在变更之前看到记录。

为了解决这个问题,我试着像这样注入自定义上下文:

builder.RegisterType<PCContext>().As<IPCContext>().InstancePerDependency();

执行此操作后,我可以看到数据库中的最新更改。但现在我有另外一个问题。当我插入新记录然后读取它时,从我的WebJob中我看不到这条新记录。在我注入上下文之前,这很好用(如上面的代码所示)。

如果我在WebJob函数中创建一个新的上下文,我可以从数据库中读取更新,但我想使用我的服务层,而不是这样:

_services.UserExport.ExportUsers();

我无法弄清楚我在这里做错了什么。基本上我想要的是每次我的WebJob功能启动时我想要创建一个新的上下文,所以我确信我有来自数据库的最新更新,我希望能够插入我的数据库并再次阅读我的WebJob使用我的服务层。

有人能指出我正确的方向吗?

请注意,我的WebJob是连续的,因此它的Autofac注册代码仅在WebJob启动时执行一次,而不是每次执行WebJob中的函数时都执行。

如果需要更多说明或代码,请与我们联系。

感谢。

1 个答案:

答案 0 :(得分:0)

根据你的描述,我在我身边测试了类似的场景,我发现我可以从我的数据库中读取和更新。我将通用RepositoryUnitOfWork定义如下,您可以参考它们:

<强>存储库:

public interface IRepository<T>
{
    T GetById(object id);

    IQueryable<T> GetAll();

    void Edit(T entity);

    void Insert(T entity);

    void Delete(T entity);

}

public class Repository<T> : IRepository<T> where T : class
{
    public DbContext context;
    public DbSet<T> dbset;
    public Repository(DbContext context)
    {
        this.context = context;
        dbset = context.Set<T>();
    }

    public T GetById(object id)
    {
        return dbset.Find(id);
    }

    public IQueryable<T> GetAll()
    {
        return dbset;
    }

    public void Insert(T entity)
    {
        dbset.Add(entity);
    }

    public void Edit(T entity)
    {
        context.Entry(entity).State = EntityState.Modified;
    }

    public void Delete(T entity)
    {
        context.Entry(entity).State = EntityState.Deleted;
    }
}

<强>的UnitOfWork:

public class UnitOfWork : IDisposable
{
    private DbContext _context;
    private Repository<TodoItem> toDoItemRepository;

    public Repository<TodoItem> ToDoItemRepository
    {
        get
        {
            if (toDoItemRepository == null)
                toDoItemRepository = new Repository<TodoItem>(_context);
            return toDoItemRepository;
        }
    }

    public UnitOfWork() : this(new BruceDbContext()) { }
    public UnitOfWork(DbContext context)
    {
        _context = context;
    }

    public void Commit()
    {
        _context.SaveChanges();
    }

    #region Dispose
    private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

对于我的WebJob,我定义了 Functions.cs 并初始化了JobActivator,如下所示:

<强> Functions.cs

public class Functions
{
    private UnitOfWork _unitOfWork;
    public Functions(UnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task CronJob([TimerTrigger("0/30 * * * * *")] TimerInfo timer, CancellationToken cancelToken)
    {
        //retrieve the latest record
        var item = _unitOfWork.ToDoItemRepository.GetAll().OrderByDescending(i => i.CreateDate).FirstOrDefault();
        Console.WriteLine($"[{item.CreateDate}] {item.Text}");

        //insert a new record
        _unitOfWork.ToDoItemRepository.Insert(new Entities.TodoItem()
        {
            Id = Guid.NewGuid().ToString(),
            CreateDate = DateTime.Now,
            Text = $"hello world -{DateTime.Now}"
        });
        _unitOfWork.Commit();

        //retrieve the previous added record
        item = _unitOfWork.ToDoItemRepository.GetAll().OrderByDescending(i => i.CreateDate).FirstOrDefault();
        Console.WriteLine($"[{item.CreateDate}] {item.Text}");
    }
}

<强> Program.cs的

var builder = new ContainerBuilder();
builder.Register<UnitOfWork>(c => new UnitOfWork(new BruceDbContext())).InstancePerDependency();
builder.RegisterType<Functions>();
var container = builder.Build();

var config = new JobHostConfiguration()
{
    JobActivator = new AutoFacJobActivator(container)
};
var host = new JobHost(config);