Форум программистов, компьютерный форум, киберфорум
C#: ASP.NET Core
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
 Аватар для firnen_dragon
25 / 25 / 4
Регистрация: 21.01.2019
Сообщений: 407

Невозможно выполнить Update т.к. объект уже отслеживается

11.02.2025, 16:34. Показов 3518. Ответов 24

Студворк — интернет-сервис помощи студентам
Пытаюсь обновить объект в бд, в запросе HttpPut, но получаю такое исключение:
Code
1
The instance of entity type 'Container' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
В контроллере:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[HttpPut("{id}")]
public async Task<IActionResult> UpdateContainer(int id, [FromBody] Container container) 
{
    try 
    {
        if (container == null)
        {
            _logger.LogError("Объект container равен null");
            return BadRequest("Объект container равен null");
        }
        if (!ModelState.IsValid)
        {
            _logger.LogError("Недопустимый объект container, отправленный от клиента.");
            return BadRequest("Недопустимый объект container");
        }
        var dbcontainer = await _repositoryManager.Container.GetContainerAsync(id, true);
        if (dbcontainer == null)
        {
            _logger.LogError($"Container c id: {id}, не был найден в базе данных.");
            return NotFound();
        }
        await _repositoryManager.Container.UpdateContainerAsync(dbcontainer, container);
        return NoContent();
    }
    catch (Exception ex)
    {
        _logger.LogError($"Что-то пошло не так внутри операции UpdateContainer: {ex.Message}");
        return StatusCode(500, "Внутренняя ошибка сервера");
    }
}
В репозитории:
C#
1
2
3
4
5
6
public async Task UpdateContainerAsync(Container dbContainer, Container container)
{
    dbContainer = _mapper.Map<Container>(container);
    Update(dbContainer);
    await Save();
}
В RepositoryBase:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
    protected BwwstorageContext _applicationContext;
    public RepositoryBase(BwwstorageContext bwwstorageContext)
    {
        _applicationContext = bwwstorageContext;
    }
 
    public IQueryable<T> FindAll(bool trackChanges) =>
        !trackChanges ?
            _applicationContext.Set<T>()
            .AsNoTracking() :
            _applicationContext.Set<T>();
 
    public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression, bool trackChanges) =>
        !trackChanges ?
            _applicationContext.Set<T>()
            .Where(expression)
            .AsNoTracking() :
            _applicationContext.Set<T>()
            .Where(expression);
 
    public void Create(T entity) => _applicationContext.Set<T>().Add(entity);
 
    public void Update(T entity) => _applicationContext.Set<T>().Update(entity);
 
    public void Delete(T entity) => _applicationContext.Set<T>().Remove(entity);
 
    public async Task Save() => await _applicationContext.SaveChangesAsync();
}
Пока решил тем, что отключил AsNoTracking() в GetContainerAsync(), но мне кажется, что это какой-то косяк и так не должно быть. При этом в Delete запросе почти то же самое и Tracking включен, а работает без исключений:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteContainer(int id) 
{
    try 
    {
        var container = await _repositoryManager.Container.GetContainerAsync(id, true);
        if (container == null)
        {
            _logger.LogError($"Container c id: {id}, не был найден в базе данных.");
            return NotFound();
        }
        await _repositoryManager.Container.DeleteContainerAsync(container);
        return NoContent();
    }
    catch (Exception ex)
    {
        _logger.LogError($"Что-то пошло не так внутри операции DeleteContainer: {ex.Message}");
        return StatusCode(500, "Внутренняя ошибка сервера");
    }
}
Подскажите может я не правильно как-то делаю Put запрос?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.02.2025, 16:34
Ответы с готовыми решениями:

Добавить в уже существующий объект свойство и положить в него объект
У меня имеется такая вложенность в редьюсере initialState = { prop1: { props2: { prop3: {id:...

CodeFirst EF Многие-ко-Многим невозможно сделать Update
Всем доброго времени суток! Существует следующая модель, для которой создается БД с помощью Code-First. public class...

Не работает UPDATE -уже замучался
Уже нет сил....нет эмоций...нет воли к победе ....Ладно ;) Ну на самом деле ХЗ в чем дело, замучался. Никаких ошибок , все нормально, но в...

24
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
13.02.2025, 17:23
Студворк — интернет-сервис помощи студентам
firnen_dragon, Calabonga, Если взять классический SqlCommand(), а не новомодный EF, то какая бы ни была схема таблиц ничего сложного в этом нет. Собирается из данных объект, сложность не имеет значения, отправляется в VM/Controller, там приводится к нужному виду и уходит в Репозиторий. На сервере СУБД пишется хранимка, которая принимает этот объект и рассовывает его по нужным таблицам в нужном порядке и возвращает, если нужно, какой-то хитрый обновлённый набор данных, который опять проходит через VM/Controller, переваривается в удобоваримый вариант для UI и показывается пользователю.
В моём проекте так и реализовано. Практически вся логика СУБД написана на хранимках, которые творят что надо безо всяких вопросов и в них передаются довольно таки сложные объекты.
1
 Аватар для Calabonga
14 / 13 / 1
Регистрация: 13.02.2025
Сообщений: 34
14.02.2025, 03:54
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Если взять классический SqlCommand(), а не новомодный EF, то какая бы ни была схема таблиц ничего сложного в этом нет.
Вроде бы никто про сложность ничего не говорил.

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
На сервере СУБД пишется хранимка
О как! Дальше читать не стал, кодовое слово "хранимка" отключило желание продолжать полемику. А то хотелось про "модные" вещи написать, как то: DDD, Unit-testing, DI... А тут даже старомодная "трехзвенная архитектура" не подходит, потому что логика, при таком подходе, не должна быть интегрирована в БД...

Спасибо, было интересно.
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
14.02.2025, 10:24
Цитата Сообщение от Calabonga Посмотреть сообщение
О как! Дальше читать не стал, кодовое слово "хранимка" отключило желание продолжать полемику. А то хотелось про "модные" вещи написать, как то: DDD, Unit-testing, DI...
Что это вдруг? А ничего что сервер СУБД внутри себя выполняет все операции гораздо быстрее, чем выполнить тоже самое внешним кодом? Что сделать быстрее и экономнее в плане разделяемых ресурсов - выполнить один запрос с вызовом хранимки, которая изменит данные хоть в 100 таблицах, или для этого же выполнить 100 запросов из приложения?
Кто сказал что все запросы не тестируются во время разработки?
Кто сказал что не используется DI? Кто сказал что нет тестов логики ПО в отношении методов работы с СУБД?
Цитата Сообщение от Calabonga Посмотреть сообщение
А тут даже старомодная "трехзвенная архитектура" не подходит, потому что логика, при таком подходе, не должна быть интегрирована в БД...
Да ладно... Логика может быть где угодно - хоть в слое Model приложения, хоть в СУБД, хоть в обоих местах сразу.
Ну расскажите мне что-то новое про "трехзвенную архитектуру", что это такое и почему хранимки в БД ей не соответствуют.
Цитата Сообщение от Calabonga Посмотреть сообщение
Спасибо, было интересно.
Пожалуйста...

Добавлено через 5 минут
Calabonga, Вот вам пример
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
CREATE PROC [dbo].[spOMTOCheckStatus](@posQty int OUTPUT, @posQtyZ int OUTPUT)
AS
BEGIN
    DECLARE @idZPos         int -- ID позиции спецификации заявки
    DECLARE @idZ            int -- ID заявки
    DECLARE @sumStor        float
    DECLARE @posEI1Z        float
    DECLARE @allPos         int
    DECLARE @allPosZ        int
    DECLARE @currentPos     int
    DECLARE @currentPosZ    int
    DECLARE @counter        int
    DECLARE @counterZ       int
    DECLARE @countSpecAll   int -- Количество позиций спецификации
    DECLARE @countSpecSet   int -- Количество позиций спецификации со статусом Поставлено
    DECLARE @countSpecProg  int -- Количество позиций спецификации со статусом Идет поставка
    DECLARE @countSpecNot   int -- Количество позиций спецификации со статусом Поставки нет
    -- Табличные переменные для прохода в цикле WHILE
    -- @idTable - табличная переменная, которая хранит ID позиций спецификации заявок
    DECLARE @idTable        TABLE (ID int NOT NULL PRIMARY KEY IDENTITY(1, 1), PosZDet int)
    -- @idTableZ - табличная переменная, которая хранит ID заявок
    DECLARE @idTableZ       TABLE (ID int NOT NULL PRIMARY KEY IDENTITY(1, 1), ZIDNum int)
 
    -- Отсекаются позиции спецификации со статусом Поставлено
    SELECT @counter = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [Status] = N'Поставлено'
 
    IF @counter > 0
        INSERT INTO @idTable ([PosZDet]) SELECT [ID_ZayavkaPod] FROM [dbo].[tblOMTOZDetails] WHERE [Status] <> N'Поставлено'
    ELSE
        INSERT INTO @idTable ([PosZDet]) SELECT [ID_ZayavkaPod] FROM [dbo].[tblOMTOZDetails]
    SET @allPos = @@ROWCOUNT
 
    -- Организация прохода по позициям спецификации с обновлением статуса в зависимости от условия
    SET @currentPos = 0
    WHILE @currentPos < @allPos
        BEGIN
            SET @currentPos = @currentPos + 1
            SELECT @idZPos = [PosZdet] FROM @idTable WHERE [ID] = @currentPos
            SELECT @sumStor = ISNULL(SUM([KolEI1]), 0) FROM [dbo].[tblOMTOStorageIn] WHERE [ID_ZayavkaPod] = @idZPos 
            SELECT @posEI1Z = [KolvoEI1] FROM [dbo].[tblOMTOZDetails] WHERE [ID_ZayavkaPod] = @idZPos
            UPDATE [dbo].[tblOMTOZDetails] SET [Status] = 
                    CASE
                        WHEN @sumStor >= @posEI1Z THEN N'Поставлено'
                        WHEN @sumStor > 0 AND @sumStor < @posEI1Z THEN N'Идет поставка'
                        ELSE N'Поставки нет'
                    END
                WHERE [ID_ZayavkaPod] = @idZPos 
        END
 
    -- Отсекаются заявки со статусом Поставлено
    SELECT @counterZ = COUNT(*) FROM [dbo].[tblOMTOZayavka] WHERE [Status] = N'Поставлено'
 
    IF @counterZ > 0
        INSERT INTO @idTableZ ([ZIDNum]) SELECT [ID_Zayavka] FROM [dbo].[tblOMTOZayavka] WHERE [Status] <> N'Поставлено'
    ELSE
        INSERT INTO @idTableZ ([ZIDNum]) SELECT [ID_Zayavka] FROM [dbo].[tblOMTOZayavka]
    SET @allPosZ = @@ROWCOUNT
 
    -- Организация прохода по номерам заявок с обновлением статуса в зависимости от статуса позиций спецификации заявки
    SET @currentPosZ = 0
    WHILE @currentPosZ < @allPosZ
        BEGIN
            SET @currentPosZ = @currentPosZ + 1
            SELECT @idZ = [ZIDNum] FROM @idTableZ WHERE [ID] = @currentPosZ
            SELECT @countSpecAll = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ
            SELECT @countSpecSet = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ AND [Status] = N'Поставлено'
            SELECT @countSpecProg = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ AND [Status] = N'Идет поставка'
            SELECT @countSpecNot = COUNT(*) FROM [dbo].[tblOMTOZDetails] WHERE [ID_Zayavka] = @idZ AND [Status] = N'Поставки нет'
            UPDATE [dbo].[tblOMTOZayavka] SET [Status] = 
                CASE
                    WHEN @countSpecAll = @countSpecSet THEN N'Поставлено'
                    WHEN (@countSpecProg > 0 OR @countSpecSet > 0) AND @countSpecSet < @countSpecAll THEN N'Идет поставка'
                    WHEN @countSpecNot = @countSpecAll THEN N'Поставки нет'
                END
            WHERE [ID_Zayavka] = @idZ
        END
    SET @posQty = @allPos -- Количество обработанных записей позиций спецификаций
    SET @posQtyZ = @allPosZ -- Количество обработанных зявок
END
Сделайте похожее на EF с одним вызовом запроса или без жора памяти на клиенте.

Добавлено через 1 час 43 минуты
firnen_dragon,
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Если взять классический SqlCommand()
Кстати EF прекрасно работает с хранимками, так что если хотите, можете воспользоваться этой возможностью.
1
 Аватар для Calabonga
14 / 13 / 1
Регистрация: 13.02.2025
Сообщений: 34
14.02.2025, 11:40
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Логика может быть где угодно
Серьёзно? Ну, покажите мне unit-тесты на вашу бизнес-логику. Хотя нет, это точно не будут unit-тесты, потому что они не должны быть привязаны к БД...

Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Сделайте похожее на EF с одним вызовом запроса или без жора памяти на клиенте.
Для меня это не проблема, просто я уже вырос и умею немного больше, чем копаться в Stored Procedures... Но раз вы предлагаете мне написать на EntityFramework, то видимо, у вас это вызывает какие-то вопросы. Простите, не хочу ничем вас обидеть, потому что написать что-то типа того, что вы предложи мне проще как раз на EntityFramework, а вот используя Stored Procedures - написать я уже "с ходу" не смогу, наверное. Когда-то я использовал только их, но уже забыл про это и просто замечательно, что появились ORMы.

Кстати, если бы с бизнес-логикой, которая находится в Stored Procedure было бы всё замечательно, то прогресс бы остановился 20 лет назад и никаких ORMов бы не появилось - это же логично. Нет?. Кстати, можете ознакомиться почему были придуманы другие решения. А если коротко, то ключевой момент "сложность" приложения.



В любом случае, в данном контексте речь идет про паттерны и шаблоны проектирования. И тут решение за вами, вы можете их использовать, а можете не использовать. Это как хорошие манеры, все про них слышали и, может даже знают, но все и не всегда их применяют и используют.

Еще раз, простите, не хочу ничем вас обидеть, но StoredProcedures для меня безмерно устаревшее понятие, даже несмотря на то, что порой приходится их "разбирать" переписывая бизнес-логику на C#.
0
 Аватар для Andrey-MSK
3368 / 2254 / 388
Регистрация: 14.08.2018
Сообщений: 7,631
Записей в блоге: 4
14.02.2025, 12:30
Цитата Сообщение от Calabonga Посмотреть сообщение
Серьёзно?
Да.
Цитата Сообщение от Calabonga Посмотреть сообщение
Ну, покажите мне unit-тесты на вашу бизнес-логику. Хотя нет, это точно не будут unit-тесты, потому что они не должны быть привязаны к БД...
И что? А как по вашему разрабатывают сложные БД? Или вы думаете там только два оператора используются
T-SQL
1
2
CREATE DATABASE ...
CREATE TABLE ...
, а всё остальное делают с помощью ORM? Или все используют возможность CodeFirst?
Цитата Сообщение от Calabonga Посмотреть сообщение
Кстати, если бы с бизнес-логикой, которая находится в Stored Procedure было бы всё замечательно, то прогресс бы остановился 20 лет назад
Расскажите это разработчикам СУБД.
Цитата Сообщение от Calabonga Посмотреть сообщение
и никаких ORMов бы не появилось - это же логично. Нет?
Нет. ORM это абстракция над Command(), и создан он только для NET. В C/C++, Java, Python и т.д. нет ничего такого и близко, все работают как и работали - Command + SQL.
Цитата Сообщение от Calabonga Посмотреть сообщение
но StoredProcedures для меня безмерно устаревшее понятие
Это лично ваше мнение и не нужно его перекладывать на всех. Если кому-то удобнее всё делать через SQL, пусть делает. Для этого я и написал своё мнение по поводу сложных объектов и как их можно с минимальными усилиями распихать по таблицам БД с помощью возможностей SQL. Тем более EF прекрасно справляется с выполнением хранимок.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.02.2025, 12:30
Помогаю со студенческими работами здесь

Не срабатывает UPDATE к уже имеющемуся значению
Добрый день уважаемые гуру! Подскажите пожалуйста, как заставить запрос добавить новые данные к имеющемуся значению? Почему не...

update.... в поиске не нашел... а решить уже не в состоянии
Проблема... строчка на PHP mysql_query(&quot;update messages set sperre=&quot;.$r_sperre.&quot; where ID=1&quot;) or die(mysql_error()); В налонично ...

Update, если ячейка уже есть в базе
Здравствуйте! Работаю с MS SQL, на данный момент разобрался как переносить в базу из экселя без прописывания циклов. Однако, код...

Невозможно создать файл так как он уже существует
Здравствуйте. Не пойму что ему нужно, вроде все правильно: Program Lol; Uses CRT; var f,t:text; st:string; ...

Невозможно создать рзадел или испоьзовать уже существующий
Доброго времени суток, уважаемые форумчане! Всех со старым новым годом. У меня при установке виндос 8 возникла следующая проблема : у меня...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
25
Ответ Создать тему
Новые блоги и статьи
[golang] Двоичная куча, min-heap
alhaos 20.05.2026
Двоичная куча Двоичная куча — структура данных, которая всегда держит самый важный элемент наготове. Представьте очередь к хилеру в игре, и очередь из игроков в приоритете те у кого меньше. . .
[golang] Breadth-First Search
alhaos 19.05.2026
BFS (Breadth-First Search) — это базовый алгоритм обхода графа в ширину, который поуровнево исследует все связанные вершины. Он начинает с выбранной точки и проверяет всех соседей, прежде чем. . .
[golang] Алгоритм «Хак Госпера»
alhaos 17.05.2026
Алгоритм «Хак Госпера» Хак Госпера (Gosper's Hack) — алгоритм нахождения следующего по величине числа с тем же количеством установленных бит. Придуман Биллом Госпером в 1970-х, опубликован в. . .
Рисование бинарного древа до 6-го колена на js, svg.
russiannick 17.05.2026
<svg width="335" height="240" viewBox="0 0 335 240" fill="#e5e1bb"> <style> <!]> </ style> <g id="bush"> </ g> </ svg> function fn(){ let rost;/ / высота древа let xx=165,yy=210,w=256;
FSharp: interface of module
DevAlt 16.05.2026
Интерфейс модуля F# позволяет управлять доступностью членов, содержащихся в реализации модуля. По-умолчанию все члены модуля доступны: module Foo let x = 10 let boo () = printfn "boo" . . .
Хитросплетение родственных связей пантеона греческих богов.
russiannick 14.05.2026
Однооконник, позволяющий узреть и изучить отдельных героев древней Греции. <!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible". . .
[golang] Угол между стрелками часов
alhaos 12.05.2026
По заданным значениям часа и минуты необходимо определить значение меньшего угла между стрелками аналогового циферблата часов. import "math" func angleClock(hour int, minutes int) float64 { . . .
Debian 13: Установка Lazarus QT5
ВитГо 09.05.2026
Эта инструкция моя компиляция инструкций volvo https:/ / www. cyberforum. ru/ blogs/ 203668/ 10753. html и его же старой инструкции по установке Lazarus с gtk2. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru