Hello. I implement a domain layer (DAL) in the project. I wrote tests for it, and I tested all the basic CRUD operations of working with the repository. One project that needs data from the DAL layer is a WPF application. I plan through autoMapper to create copies of the objects I need (in order not to make binding directly to the local EF cache). Faced with the problem of updating data.

ESSENCE OF STATION

public class Station { [Key] public int Id { get; set; } [Required(ErrorMessage = "Введите Ecp код станции")] public int EcpCode { get; set; } public string Name { get; set; } } 

OBTAINING DATA, CREATING COPIES, EDITING COPIES, SAVING COPIES.

  var station = _unitOfWork.StationRepository.GetById(1); var copyStation = new Station { Id = station.Id, Name = "qqqq", //Поменяли значение EcpCode = station.EcpCode, Description = station.Description }; _unitOfWork.StationRepository.Update(copyStation); await _unitOfWork.SaveAsync(); 

REPOSITORIES

 public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class { protected CisDbContext Context { get; } protected DbSet<TEntity> DbSet { get; } public GenericRepository(CisDbContext context) { Context = context; DbSet = context.Set<TEntity>(); } public virtual void Update(TEntity entity) { DbSet.Attach(entity); //ИСКЛЮЧЕНИЕ!!!!!!!!! (объект с таким ID уже есть) Context.Entry(entity).State = EntityState.Modified; } public virtual void Update(TEntity entity, int pkDetached) { var existing = GetById(pkDetached); if (existing != null) Context.Entry(existing).State = EntityState.Detached; DbSet.Attach(entity); Context.Entry(entity).State = EntityState.Modified; } } 

When performing Update an exception is thrown.

An exception of type 'System.InvalidOperationException' occurred in

EntityFramework.dll but was not handled in user code

Additional information: Domain.Entities. This can be what happens when you see the graph of the question. The database generated key values. In this case, it should be noted that this is the case.

To solve the problem, I added a method to the repository.

  public virtual void Update(TEntity entity, int pkDetached) { var existing = GetById(pkDetached); if (existing != null) Context.Entry(existing).State = EntityState.Detached; DbSet.Attach(entity); Context.Entry(entity).State = EntityState.Modified; } 

Those. I detach an existing property with the same ID before the DbSet.Attach(entity) ;

In this case, it will work, but if in essence there will be references to other types (links to other tables). then the problem arises again.

Who faced with this please help)))

  • If the Get method returns a copy of an object, then the Update method should not add this copy to the context, but look for the corresponding original in the context and synchronize it with the copy. - Uranus
  • The Get method returns the object itself from the database, on its basis a new object is created with the same Id. The new object is edited and must replace the old one in the database (with the values ​​of its fields replace the old values). - Aldmi
  • I actually put it too vividly and in isolation from your code. By Get \ Update methods, I meant your code at the beginning and at the end of the fragment under the heading GETTING DATA, as if it were divided into separate methods. It happened by chance. I just wanted to say that if you made a copy of an object to perform actions on it, then you cannot add this copy to the context. It is logically true to find the original in the context, synchronize the changes, then save them to the database. - Uranus
  • I understood you. But it is quite difficult, because if nested objects change as well (choosing from the list of objects from another table), then you need to find the selected object by Id. Well, so all the connections need to be brought back into line with the context. Hm thought it would be easier. - Aldmi
  • On the bottom I encountered such an error, in my case it was due to the fact that the auto-reader created a new object. This decision helped me - Ruslan_K

0