Проблема обновления единицы работы: Объект Уже отслеживается, другой экземпляр уже отслеживается

#c# #entity-framework-5 #unit-of-work

Вопрос:

У меня проблема с реализацией шаблона UOW ( мой UOW использует шаблон репозитория ). Я попытаюсь объяснить структуру моего проекта двумя простыми способами. У меня есть Человек и машина (один ко многим — один к одному).

 [Table("Person")]
public class Person
{
    public int id{ get; set; }
    public string name{ get; set; }
    public IList<Car> cars_owned{ get; set; }

}
 

и

 [Table("Car")]
public class Car
{
    public int id{ get; set; }
    public Person owner{ get; set; }
}
 

В моей реализации CarServiceImplementation я хочу реализовать свой AddUpdateCar (), чтобы добавить «Человека», если он не существует, или обновить его.

Это моя фактическая реализация:

 public async Task<bool> addUpdateCar(AddUpdateCarModel model)
        {
            var car = await unitOfWork.CarRepository.GetByID(model.car_id);
            var person = await unitOfWork.PersonRepository.GetByID(model.person.id);
            if (person == null)
            {
                unitOfWork.PersonRepository.Insert(model.person);
            }
            else
            {
                unitOfWork.PersonRepository.Update(model.person);
            }

            car.owner = model.person;
            unitOfWork.CarRepository.Update(car);
            unitOfWork.Save();
            return true;
        }
 

Этот вид импл говорит: Экземпляр сущности типа «Person» не может быть отслежен, потому что другой экземпляр с тем же значением ключа для {«id»} уже отслеживается.

Я также пробовал разные способы, но у меня есть другие проблемы.

Как правильно реализовать этот метод?

ПРАВКА 1:

 public void Update(Person p)
{
    context.Entry(p).State = EntityState.Modified;
}
 

и

 public async Task<Person> GetByID(int id)
        {
            return await context.person.FindAsync(id);
        }
 

Комментарии:

1. пожалуйста, опубликуйте свой UnitOfWork.PersonRepository. Обновление(модель.человек); и код GetById, пожалуйста

2. Правка 1, спасибо за ответ

3. @Limitless немного не по теме, но почему вы скрываете репозитории от своих служб за объектом UOW? Это делается для простоты (в противном случае вам пришлось бы явно вводить каждый репозиторий в свои службы приложений)? Интересно, является ли откровенность лучшим дизайнерским решением?

Ответ №1:

Поскольку вы используете единицу работы, проще всего было бы добавить новый метод в PersonRepository

 public void InsertOrUpdate(Person p)
{
    var existedPerson = GetByID(p.id);
    if (existedPerson != null) 
        context.Entry(existedPerson).CurrentValues.SetValues(p);
    else Insert(p);
}
 

Комментарии:

1. Спасибо, это работает. Я был сосредоточен на сервисах, а не на репозитории.