EntityKey 및 ApplyPropertyChanges ()

.net asp.net-mvc c# entity-framework

문제

EntityObject의 EntityKey를 설정해야합니다. 나는 그것의 타입과 id 값을 안다. 불필요하게 데이터베이스를 쿼리하고 싶지 않습니다.

이 작품은 ...

//
// POST: /Department/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    Model.EntityKey = (from Department d in db.Department
                       where d.Id == id
                       select d).FirstOrDefault().EntityKey;
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

이것은 실패 ...

//
// POST: /Department/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    String EntitySetName = db.DefaultContainerName + "." + Model.GetType().Name;
    Model.EntityKey = new System.Data.EntityKey(EntitySetName, "Id", Model.Id);
    db.ApplyPropertyChanges(Model.EntityKey.EntitySetName, Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

ApplyPropertyChanges () 행은이 예외와 함께 실패합니다.

ObjectStateManager에는 'Sample.Models.Department'유형의 개체에 대한 참조가있는 ObjectStateEntry가 포함되어 있지 않습니다.

두 EntityKeys는 동일합니다. 두 번째 코드 블록이 실패하는 이유는 무엇입니까? 어떻게 해결할 수 있습니까?

인기 답변

두 번째 코드 블록이 실패하는 이유는 EF가 ObjectStateManager에서 개체를 찾을 수 없기 때문입니다. 즉, 개체를 db에서 가져 와서 상태 관리자에 놓아서 개체를 추적 할 수 있습니다. 이는 ID 맵 패턴과 유사합니다 . EntityKey가 있더라도 개체는 상태 관리자가 아니므로 EF는 변경 내용을 유지할 수 없습니다. 객체를 상태 관리자 자신에게 넘겨줌으로써이 문제를 해결할 수 있습니다. 그러나 당신은 그것에 대해 조금 비열합니다.

작동 방식 :

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  var entitySetName = db.DefaultContainerName + "." + model.GetType().Name;
  var entityKey = new System.Data.EntityKey(entitySetName, "Id", model.Id);

  db.Attach(new Department{Id = id, EntityKey = entityKey});
  db.AcceptAllChanges();

  db.ApplyPropertyChanges(entitySetName, model);
  db.SaveChanges();
}

...하지만 그다지 깨끗하지는 않습니다. 기본적으로 엔티티 키만으로 '빈'객체를 첨부하고 모든 변경 사항을 수락 한 다음 실제 실제 업데이트 된 값으로 ApplyPropertyChanges를 호출합니다.

확장 메소드에서 같은 것을 사용합니다. 기본 키에 대해 단일 db 컬럼을 사용하는 모든 것이 작동합니다. 이 메서드를 호출하는 유일한 흥미로운 부분은 확장 메서드의 두 번째 인수로 대리자를 통해 키 속성을 찾는 방법을 알려야한다는 것입니다.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department model)
{
  db.ApplyDetachedPropertyChanges(model, x => x.Id);
  db.SaveChanges();
}

및 확장 방법 :

public static class EfExtensions
{
  public static void ApplyDetachedPropertyChanges<T>(this ObjectContext db, T entity, Func<T, int> getIdDelegate)
  where T : EntityObject
  {
    var entitySetName = db.DefaultContainerName + "." + entity.GetType().Name;
    var id = getIdDelegate(entity);
    var entityKey = new EntityKey(entitySetName, "Id", id);

    db.Attach(new Department {Id = id, EntityKey = entityKey});
    db.AcceptAllChanges();

    db.ApplyPropertyChanges(entitySetName, entity);
  }
}

확장 메서드가 AcceptAllChanges를 호출 할 때 여러 엔터티에 대한 업데이트를 동시에 수행하는 경우이 메서드를 호출 할 때주의해야합니다. 조심하지 않으면 업데이트를 쉽게 잃을 수 있습니다. 따라서이 접근법은 단순한 업데이트 시나리오에만 적합합니다. 예를 들어, 많은 MVC 작업 방법 :)



Related

아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.