powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / An entity object cannot be referenced by multiple instances of IEntityChangeTracker
2 сообщений из 2, страница 1 из 1
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
    #38945095
KononovAI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

Подскажите, как можно разрулить такую ситуацию.

Пишу Asp.NET MVC приложение.
В качестве IoC использую Ninject
Работа с БД осуществляется через EntityFramework (CodeFirst)

Код инициализации ninject:
Код: c#
1.
2.
3.
4.
5.
6.
7.
            // Database
            kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
            kernel.Bind(typeof(IUnitOfWork)).To(typeof(UnitOfWork));
            kernel.Bind<IDbContext>().To<EntityContext>().InScope(ctx => HttpContext.Current);
            // Services
            kernel.Bind<ITriggerService>().To<TriggerService>();
            kernel.Bind<IMailTaskService>().To<MailTaskService>();



Код DBContext:

Код: c#
1.
public DbSet<MailTask> MailTasks { get; set; }



В MailTasks лежат записи с письмами, которые надо отослать в определенные даты.
Для этого в MailTaskService написан метод "ProcessMailTaskQueue()", который навешивается на триггер, запускаемый раз в минуту.
Инициализация триггера делается в global.asax.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
private void StartPeriodicalTasks()
        {
            var taskListService = DependencyResolver.Current.GetService<ITriggerService>();
            var mailService = DependencyResolver.Current.GetService<IMailTaskService>();
            
            // Обработка очереди отправки оповещений по электронной почте
            taskListService.AddTask(() =>
            {
                mailService.ProcessMailTaskQueue();
            }, 1);
        }



Функции отправки письма такие:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
/// <summary>
        /// Обработка очереди почтовых оповещений
        /// </summary>
        public void ProcessMailTaskQueue()
        {
            // Находим элементы, которые должны быть отправлены
            var tasks = RepositoryHelper.MailTasks.GetAll().Where(t => t.SendDate <= DateTime.Now).ToList();
            foreach (var tsk in tasks)
            {
                // Отправляем письмо
                var res = SendMail(tsk);
                // Если письмо не удалось отправить, то прерываем операцию, чтобы попробовать позже
                if (!res.Succeeded)
                    break;
            }
        }



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
        public MethodResult SendMail(MailTask mailTask)
        {
            if (mailTask == null)
                return MethodResult.Error("Объект MailTask не определен");

            // Отправляем письмо
            var res = SendMail(mailTask.Subject, mailTask.To, mailTask.Body);
            // Если письмо отправлено, то удаляем письмо из очереди
            if (res.Succeeded)
            {
                res = DeleteMailTask(mailTask);
            }
            // Возвращаем результат
            return res;
        }



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
        public MethodResult DeleteMailTask(MailTask task)
        {
            if (task == null) return MethodResult.Error("Параметр task не передан");

            try
            {
                RepositoryHelper.MailTasks.Delete(task);
                RepositoryHelper.Commit();

                return MethodResult.Success();
            }
            catch (Exception e)
            {
                return MethodResult.Error(e.Message);
            }
        }



RepositoryHelper - статический класс, который через DependencyResolver достает нужный интерфейс.

При отработке метода на строке "RepositoryHelper.MailTasks.Delete(task);" ловится ошибка "An entity object cannot be referenced by multiple instances of IEntityChangeTracker".

Если ninject инициировать так:
Код: c#
1.
kernel.Bind<IDbContext>().To<EntityContext>().InSingletonScope();


то все работает нормально.
Но не уверен, что такая инициализация здесь применима.

Попробовал написать отдельный Action, который просто запускает "ProcessMailTaskQueue" и дернуть его из браузера - все отрабатывает замечательно.


Мне кажется, что в случае, когда запуск "ProcessMailTaskQueue" осуществляется через триггер DBContext создается свой при каждом обращении, так как в этом случае нет никакого http-request-а.

Подскажите, как можно настроить время жизни DBContext или как можно по иному решить задачу.

Спасибо.
...
Рейтинг: 0 / 0
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
    #38945216
Фотография Абсолют
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KononovAI,

Код: c#
1.
kernel.Bind<IDbContext>().To<EntityContext>().InSingletonScope();


Так делать в веб точно не надо.

Копать здесь:
InRequestScope
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / An entity object cannot be referenced by multiple instances of IEntityChangeTracker
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]