Autofac - получение нового экземпляра UnitOfWork - «DBcontext был удален ошибка» - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть пакетное задание, которое анализирует файл CSV, создает и обрабатывает записи.В каждой строке я должен выполнять коммиты, так как мне нужно создавать сущности, а затем использовать результаты созданных сущностей.

Поскольку существует тысячи записей, производительность снижается, и я пытаюсь улучшить свою производительность.

У меня есть код, который выглядит примерно так:

var data = ParseExcel(filePath);
Setup();

foreach (var batch in data.Split(20))
{
    foreach (var row in batch)
    {
        try
        {
            ParseRow(row);
        }
        catch (Exception e)
        {
            JobLogger.Error(e, "Failed to parse row. Exception: " + e.Message);
            throw;
        }
    }

    _unitOfWork.Commit();
    _unitOfWork.Dispose();
    _unitOfWork = LifetimeScope.Resolve<Owned<IUnitOfWork>>().Value;
    ClientRepository = LifetimeScope.Resolve<Owned<IEntityBaseRepository<Client>>>().Value;

Мой метод Dispose выглядит следующим образом:

public void Dispose()
{
    _dbContext.Dispose();
    _dbContext = null;
    _dbFactory.Dispose();
    _dbFactory = null;
    GC.SuppressFinalize(this);
}

Намерение здесь заключается в том, что после каждой партии записейобработан, я хочу обновить единицу работы, утилизировав ее и запросив, чтобы Autofac сгенерировал ее новый экземпляр.

Однако, когда я добавляю элемент в мой ClientRepository, он падает с ошибкой:

Операция не может быть завершена из-за удаления DbContext.

Мой ClientRepository использует общий класс репозитория, который выглядит следующим образом:

public class EntityBaseRepository<T> : IEntityBaseRepository<T> where T : class, IEntityBase, new()
    {
        private DataContext _dataContext;

        #region Properties
        protected IDbFactory DbFactory
        {
            get;
        }

        protected DataContext DbContext => _dataContext ?? (_dataContext = DbFactory.Initialise());

        public EntityBaseRepository(IDbFactory dbFactory)
        {
            DbFactory = dbFactory;
        }

        #endregion

Вот часть моего UnitOfWork:

public class UnitOfWork : IUnitOfWork, IDisposable
{
    private IDbFactory _dbFactory;
    private DataContext _dbContext;

    public UnitOfWork(IDbFactory dbFactory)
    {
        _dbFactory = dbFactory;
    }

    public DataContext DbContext => _dbContext ?? (_dbContext = _dbFactory.Initialise());

    public void Commit()
    {
        DbContext.Commit();
    }

Любые мысли опочему я все еще получаю эту ошибку?

1 Ответ

0 голосов
/ 13 января 2019

Чтобы убедиться, что я получаю новый экземпляр моего UnitOfWork после каждого пакета операций, я извлекаю ссылку на мою текущую область действия Autofac и прошу Autofac дать мне новую область действия жизни в операторе using, затем я использую Autofac для регистрациии разрешить эти зависимости.Некоторые из моих служб также зависят от UnitOfWork, поэтому было важно получить новые экземпляры этих зависимостей.

Вот фрагмент кода:

foreach (var batch in data.Split(10))
{
    using (var scope = LifetimeScope.BeginLifetimeScope("UnitOfWork", b =>
    {
        b.RegisterType<UnitOfWork>().AsImplementedInterfaces().InstancePerLifetimeScope();
        b.RegisterType<MyService>().AsImplementedInterfaces().PropertiesAutowired().InstancePerLifetimeScope();
        b.RegisterGeneric(typeof(EntityBaseRepository<>)).As(typeof(IEntityBaseRepository<>)).InstancePerLifetimeScope();
    }))
    {
        UnitOfWork = scope.Resolve<IUnitOfWork>();
        MyService = scope.Resolve<IMyService>();

        foreach (var row in batch)
        {
            try
            {
                ParseRow(row);
            }
            catch (Exception e)
            {
                JobLogger.Error(e, "Failed to parse row. Exception: " + e.Message);
                throw;
            }

        }
    }
}

В приведенном выше коде я присвоил имя UnitOfWork вложенной области действия времени жизни.

С этим кодом производительность работы значительно улучшилась, так как в этот раз я не использовал один и тот же экземпляр UnitOfWork, который отслеживал десятки тысяч изменений при обработке файла.

Кроме того, я перестал разбивать данные на пакеты по 10 - я решил получить новый UnitOfWork после обработки каждой строки, поскольку каждая строка уже включала вставку данных как минимум в 10 различных таблиц.

...