Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: ASP.NET Core
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
yurickas
54 / 45 / 16
Регистрация: 25.11.2015
Сообщений: 457
Завершенные тесты: 1
1

ASP.NET Core: не работает метод Update EF после Automapper

28.04.2017, 08:54. Просмотров 1385. Ответов 10
Метки нет (Все метки)

Собственно вот. При сохранении записи в базу данных выдает исключение, что данный экземпляр объекта не отслеживается. Поле Id не имеет значение Default, поэтому EF не может понять переписать существующую запись с таким же Id или создать новую.

Собака порылась в Automapper. Если опишем метод вот так:
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
31
32
33
34
35
36
37
38
[HttpPost("Edit")]
        public void EditClient([FromBody] ClientEditViewModel model)
        {
            DirectoryClient client;
 
            if (model.IsPeople)
            {
                model.Name = EditPeopleName.GetPeopleName(model.Surname, model.FirstName, model.MiddleName);
                model.FullName = EditPeopleName.GetPeopleFullName(model.Surname, model.FirstName, model.MiddleName);
            }
 
            if (model.Id == Guid.Empty)
            {
                Mapper.Initialize(cfg => cfg.CreateMap<ClientEditViewModel, DirectoryClient>());
                client = Mapper.Map<ClientEditViewModel, DirectoryClient>(model);
 
                clientsRepository.Add(client);
            }
            else
            {
                client = clientsRepository.Get(model.Id);
                //Mapper.Initialize(cfg => cfg.CreateMap<ClientEditViewModel, DirectoryClient>());
                //client = Mapper.Map<ClientEditViewModel, DirectoryClient>(model);
                client.IsPeople = model.IsPeople;
                client.Address = model.Address;
                client.FirstName = model.FirstName;
                client.FullName = model.FullName;
                client.MiddleName = model.MiddleName;
                client.Name = model.Name;
                client.Okpo = model.Okpo;
                client.PhoneNumber = model.PhoneNumber;
                client.Surname = model.Surname;
                client.Unp = model.Unp;
                clientsRepository.Update(client);
            }
 
 
        }
то все работает. Но раньше все работало без этих костылей. Есть у меня в репозитории метод Save.
C#
1
2
3
4
5
6
7
8
9
10
11
12
public Guid Save(TEntity document)
        {
            if (((IEntity)document).Id == Guid.Empty)
            {
                return Add(document);
            }
            else
            {
                return Update(document);
            }
 
        }
т.е. я раньше тупо получал модель представления, Automapper тупо давал мне сущность по представлению, репозиторий тупо проверял Id и добавлял или изменял запись в БД. Сейчас все поломалося.

Раньше у меня было обычное веб-приложение. Сейчас контроллер у меня WebAPI. Может в этом причина?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.04.2017, 08:54
Ответы с готовыми решениями:

ASP.NET Core + AngularJs. Не работает метод success сервиса $http
Собственно, вот. Разбираюсь с работой Angular. Вроде все работает, но стала проблема с работой...

ASP.NET Core. Старт - что нужно знать, чтобы стать ASP.NET Core разработчиком?
Попалось хор краткое обзорное видео 2016 года с таким названием - Что нужно знать, чтобы стать...

Разница между ASP.NET Core 2, ASP.NET Core MVC, ASP.NET MVC 5 и ASP.NET WEBAPI 2
Здравствуйте. Я в бекенд разработке полный ноль. В чем разница между вышеперечисленными...

Какая разница между ASP .Net Core и ASP .Net Core MVC?
Какая разница между ASP .Net Core и ASP .Net Core MVC? Или я может что-то не так понял? И...

ASP.NET Core. Форма не работает с кириллицей
Собственно вот, штудирую ASP.NET Core. Делаю пример из мсдн, а там ессно все на буржуйском. Но я же...

10
Usaga
Эксперт .NET
5556 / 3760 / 668
Регистрация: 21.01.2016
Сообщений: 14,974
Завершенные тесты: 2
28.04.2017, 09:03 2
yurickas, о боже. Вы Automapper иниицализируете в каждом методе, где его используете?..
0
yurickas
54 / 45 / 16
Регистрация: 25.11.2015
Сообщений: 457
Завершенные тесты: 1
28.04.2017, 09:17  [ТС] 3
Нет. Когда все было написано одной сточкой и работало недели 2 назад, то все было красиво и Automapper инициировался там где нужно.
Когда я добавил запись в БД - тоже все было хорошо. Но когда я попытался изменить запись в БД - получил ошибку сервера. А когда получил - начал забивать костыли, шоб это все заработало и понять где поломалось.

Пока что придумать не могу где поломалось. Раньше EF прекрасно сохранял изменения в БД после Automapper и ему было все-равно вытянул я запись из репозитория, изменил и отправил на сохранение, или создал новый экземпляр заполнил и отправил на сохранение.
0
Usaga
Эксперт .NET
5556 / 3760 / 668
Регистрация: 21.01.2016
Сообщений: 14,974
Завершенные тесты: 2
28.04.2017, 11:59 4
yurickas, можете сотворить минимальный рабочий пример, где ошибка воспроизводится? Или свой текущий проект очистить от всего лишнего, оставив скелет, и выложить на форум. Ибо так сложно что-то сказать.
0
yurickas
54 / 45 / 16
Регистрация: 25.11.2015
Сообщений: 457
Завершенные тесты: 1
29.04.2017, 07:47  [ТС] 5
напишу следующий контроллер, выложу.

Добавлено через 17 часов 16 минут
Вот такое описание к ошибке.
The instance of entity type 'DirectoryUnit' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

Вот контроллер
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
31
32
33
34
35
36
37
38
39
40
[Produces("application/json")]
    [Route("api/Units")]
    public class UnitsController : Controller
    {
        private IRepository<DirectoryUnit> repository;
 
        public UnitsController(IRepository<DirectoryUnit> repo)
        {
            repository = repo;
        }
 
        [Route("Units")]
        public IActionResult Index() => View();
 
        [HttpGet("Get")]
        public IEnumerable<UnitEditViewModel> Get()
        {
            Mapper.Initialize(cfg => cfg.CreateMap<DirectoryUnit, UnitEditViewModel>());
            return repository.EntityList.OrderBy(p => p.Name).
                Select(x => Mapper.Map<DirectoryUnit, UnitEditViewModel>(x));
        }
 
        [HttpGet("Get/{id}")]
        public UnitEditViewModel Get(Guid id)
        {
            Mapper.Initialize(cfg => cfg.CreateMap<DirectoryUnit, UnitEditViewModel>());
            return Mapper.Map<DirectoryUnit, UnitEditViewModel>(repository.Get(id));
        }
 
        [HttpPost("Edit")]
        public void Edit([FromBody] UnitEditViewModel model)
        {
            Mapper.Initialize(cfg => cfg.CreateMap<UnitEditViewModel, DirectoryUnit>());
            DirectoryUnit unit = Mapper.Map<UnitEditViewModel, DirectoryUnit>(model);
 
            repository.Save(unit);
        }
 
 
    }
А вот класс репозитория

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
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
public class EFRepository<TEntity> : IRepository<TEntity> where TEntity:class
    {
 
        private ApplicationDbContext context;
        public EFRepository(ApplicationDbContext ctx)
        {
            context = ctx;
        }
 
        public IQueryable<TEntity> EntityList
        {
            get
            {
                return context.Set<TEntity>();
            }
        }
 
        public Guid Add(TEntity document)
        {
            context.Set<TEntity>().Add(document);
            context.SaveChanges(true);
            return ((IEntity)document).Id;
        }
 
        public void Delete(TEntity document)
        {
            context.Set<TEntity>().Remove(document);
            context.SaveChanges(true);
        }
 
        public TEntity Get(Guid id)
        {
            return context.Set<TEntity>().FirstOrDefault(p => ((IEntity)p).Id == id);
        }
 
        public Guid Save(TEntity document)
        {
            if (((IEntity)document).Id == Guid.Empty)
            {
                return Add(document);
            }
            else
            {
                return Update(document);
            }
 
        }
 
        public Guid Update(TEntity document)
        {
            context.Update<TEntity>(document);
            context.SaveChanges();
            return ((IEntity)document).Id;
        }
 
    }
0
Usaga
Эксперт .NET
5556 / 3760 / 668
Регистрация: 21.01.2016
Сообщений: 14,974
Завершенные тесты: 2
29.04.2017, 08:38 6
yurickas, у вас репозиторий, видимо, представлен синглтоном. Создавайте экземпляр репозитория и контекста на запрос, а не на всё приложение. Используйте метод AsNoTracking() для получения сущностей без сохранения их в кэше.
1
yurickas
54 / 45 / 16
Регистрация: 25.11.2015
Сообщений: 457
Завершенные тесты: 1
29.04.2017, 08:45  [ТС] 7
Да, синглтоном. А теперь можно повторить тоже самое, но для людей со средним техническим образованием?
0
Usaga
Эксперт .NET
5556 / 3760 / 668
Регистрация: 21.01.2016
Сообщений: 14,974
Завершенные тесты: 2
29.04.2017, 08:55 8
yurickas, время жизни контекста и репозитория должно быть ограничено запросом. Т.е. не надо использовать синглтон.

По AsNoTracking можно и погуглить.
1
yurickas
54 / 45 / 16
Регистрация: 25.11.2015
Сообщений: 457
Завершенные тесты: 1
29.04.2017, 09:01  [ТС] 9
А чем тогда пользоваться? Был AddTransient, но тогда на WebAPI запросы как-то непонятно выполняются. А кроме них я и не знаю больше.

нашёль!!! AddScoped?
0
Usaga
Эксперт .NET
5556 / 3760 / 668
Регистрация: 21.01.2016
Сообщений: 14,974
Завершенные тесты: 2
29.04.2017, 09:06 10
Лучший ответ Сообщение было отмечено yurickas как решение

Решение

yurickas, вам нужно настроить DI контейнер на Scoped для репозитория. Непонятность выполнения запросов связана с неправильным использованием EF и кривизной кода.
1
yurickas
54 / 45 / 16
Регистрация: 25.11.2015
Сообщений: 457
Завершенные тесты: 1
29.04.2017, 09:11  [ТС] 11
Все, заработало. Щас плюсов накидаю.
0
29.04.2017, 09:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.04.2017, 09:11

ASP.NET Core Не собирается проект после обновления NuGet
Собственно вот. Сижу, никого не трогаю, книжку штудирую, по клаве постукиваю. По книжке...

ASP.NET Core: разный формат даты контроллера ASP.NET и AngularJS
Собственно, проблему пока еще не разруливал, но уже погуглил. Разный формат даты который использует...

ASP.NET Core по книге А.Фримена. Не работает там один пример
И даже не знаю почему. Собственно вот, разбираю книгу. Делаю тамошний магазин. Застопорился на том...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru