Форум программистов, компьютерный форум, киберфорум
C#: ASP.NET Core
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
163 / 138 / 35
Регистрация: 25.11.2015
Сообщений: 910
1

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

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

Author24 — интернет-сервис помощи студентам
Собственно вот. При сохранении записи в базу данных выдает исключение, что данный экземпляр объекта не отслеживается. Поле 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)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.04.2017, 08:54
Ответы с готовыми решениями:

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

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

ASP.NET Core + EF Core: ошибка при обновлении БД после создания миграции
Всем привет! Начал осваивать ASP.NET Core: создал проект &quot;Веб-приложение&quot; без Identity. Сразу же...

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

10
Эксперт .NET
12083 / 8391 / 1283
Регистрация: 21.01.2016
Сообщений: 31,641
28.04.2017, 09:03 2
yurickas, о боже. Вы Automapper иниицализируете в каждом методе, где его используете?..
0
163 / 138 / 35
Регистрация: 25.11.2015
Сообщений: 910
28.04.2017, 09:17  [ТС] 3
Нет. Когда все было написано одной сточкой и работало недели 2 назад, то все было красиво и Automapper инициировался там где нужно.
Когда я добавил запись в БД - тоже все было хорошо. Но когда я попытался изменить запись в БД - получил ошибку сервера. А когда получил - начал забивать костыли, шоб это все заработало и понять где поломалось.

Пока что придумать не могу где поломалось. Раньше EF прекрасно сохранял изменения в БД после Automapper и ему было все-равно вытянул я запись из репозитория, изменил и отправил на сохранение, или создал новый экземпляр заполнил и отправил на сохранение.
0
Эксперт .NET
12083 / 8391 / 1283
Регистрация: 21.01.2016
Сообщений: 31,641
28.04.2017, 11:59 4
yurickas, можете сотворить минимальный рабочий пример, где ошибка воспроизводится? Или свой текущий проект очистить от всего лишнего, оставив скелет, и выложить на форум. Ибо так сложно что-то сказать.
0
163 / 138 / 35
Регистрация: 25.11.2015
Сообщений: 910
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
Эксперт .NET
12083 / 8391 / 1283
Регистрация: 21.01.2016
Сообщений: 31,641
29.04.2017, 08:38 6
yurickas, у вас репозиторий, видимо, представлен синглтоном. Создавайте экземпляр репозитория и контекста на запрос, а не на всё приложение. Используйте метод AsNoTracking() для получения сущностей без сохранения их в кэше.
1
163 / 138 / 35
Регистрация: 25.11.2015
Сообщений: 910
29.04.2017, 08:45  [ТС] 7
Да, синглтоном. А теперь можно повторить тоже самое, но для людей со средним техническим образованием?
0
Эксперт .NET
12083 / 8391 / 1283
Регистрация: 21.01.2016
Сообщений: 31,641
29.04.2017, 08:55 8
yurickas, время жизни контекста и репозитория должно быть ограничено запросом. Т.е. не надо использовать синглтон.

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

нашёль!!! AddScoped?
0
Эксперт .NET
12083 / 8391 / 1283
Регистрация: 21.01.2016
Сообщений: 31,641
29.04.2017, 09:06 10
Лучший ответ Сообщение было отмечено yurickas как решение

Решение

yurickas, вам нужно настроить DI контейнер на Scoped для репозитория. Непонятность выполнения запросов связана с неправильным использованием EF и кривизной кода.
1
163 / 138 / 35
Регистрация: 25.11.2015
Сообщений: 910
29.04.2017, 09:11  [ТС] 11
Все, заработало. Щас плюсов накидаю.
0
29.04.2017, 09:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.04.2017, 09:11
Помогаю со студенческими работами здесь

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

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

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

ASP .NET MVC. Core 2.1. Не работает страница веб-приложения
ASP. NET Core 2.1 MVC, DB Postgresql. Проблема такая, не могу загрузить на сайте index.cshtml ...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru