Не удается сохранить изменения в контексте базы данных

У меня проблема с сохранением изменений в контексте базы данных. Когда я не сохраняю, я вижу, что статус списка успешно изменен, но когда я пытаюсь сохранить его, я получаю сообщение об ошибке: «Уже есть открытый DataReader, связанный с этим соединением, который должен быть закрыт в первую очередь». И я не знаю, откуда это. Когда я пытаюсь сделать это асинхронно, я получаю ту же ошибку.

АдминистраторКонтроллер.cs

 [Route("/Admin")]
    [ApiController]


    public class AdministratorController : Controller
    {
        private readonly dbContext _dbContext;

        public AdministratorController(dbContext dbContext)
        {
            _dbContext = dbContext;
        }


        ///////////////////////////////////
        ///                             //
        ///   Accept or Reject Listings //
        ///                             //
        //////////////////////////////////
        [HttpPost]
        [Route("acceptListing/{listingId}")]
        [AllowAnonymous]
        //[Authorize(Roles = "Administrator")]
        public ActionResult AcceptList([FromRoute]int listingId)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest();
            }
            if (listingId == null)
            {
                return NotFound("Listing not found.");
            }

            foreach (Listing listing in _dbContext.Listings)
            {
                Console.WriteLine(listing.Status);
                if (listing.Id == listingId)
                {
                    if (listing.Status == ListingStatus.Accepted)
                    {
                        return BadRequest("Listing already accepted.");
                    }
                    else
                    {
                        listing.Status = ListingStatus.Accepted;
                        Console.WriteLine(listing.Status);
                        _dbContext.SaveChanges();

                    }
                    return Ok();
                }
            }

            return BadRequest("Couldn't find right listing.");
        }

Да, это его проблема, он повторяет список, изменяя их в том же цикле.

Mocas 22.12.2022 18:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Проблема здесь в том, что вы повторяете данные, извлекаемые из базы данных, и в то же время пытаетесь сохранить что-то из того же контекста. Быстрое решение - использовать ToList в foreach:

foreach (Listing listing in _dbContext.Listings.ToList())
{
   // ..
}

Но в целом вам не следует извлекать из базы данных все, чтобы обработать только один элемент. Просто напишите запрос, который будет фильтровать все на стороне базы данных. Что-то в этом роде (не проверено):

var listing = _dbContext.Listings.FirstOrDefault(l => l.Id == listingId);
if (listing is null)
{
    return NotFound();
}

if (listing.Status == ListingStatus.Accepted)
{
    return BadRequest("Listing already accepted.");
}
else
{
    listing.Status = ListingStatus.Accepted;
    Console.WriteLine(listing.Status);
    _dbContext.SaveChanges();
}
return Ok();

изменить код следующим образом:

var listings = _dbContext.Listings.Tolist();
foreach (Listing listing in listings)
        {
            Console.WriteLine(listing.Status);
            if (listing.Id == listingId)
            {
                if (listing.Status == ListingStatus.Accepted)
                {
                    return BadRequest("Listing already accepted.");
                }
                else
                {
                    listing.Status = ListingStatus.Accepted;
                    Console.WriteLine(listing.Status);
                    _dbContext.Update(listing);
                    _dbContext.SaveChanges();
                }
                return Ok();
            }
        }
Ответ принят как подходящий

Вместо того, чтобы перебирать все списки в поисках нужного идентификатора, просто отфильтруйте и получите.

Listing? listing = _dbContext.Listings.FirstOrDefault(l => l.Id == listingId);

if (listing is null)
{
    return BadRequest("Couldn't find right listing.");
}     

if (listing.Status == ListingStatus.Accepted)
{
    return BadRequest("Listing already accepted.");
}

listing.Status = ListingStatus.Accepted;
Console.WriteLine(listing.Status);
_dbContext.SaveChanges();

return Ok();

Другие вопросы по теме