2010-05-05 4 views
2

문제 추적 응용 프로그램의 간단한 편집 양식을 만들고 싶습니다. 단순 들어, HttpGet 편집 작업은 다음과 같이 보입니다 :편집 동작에서 RowVersion과 ASP.NET MVC 동시성

// Issues/Edit/12 
    public ActionResult Edit(int id) 
    { 
     var thisIssue = edmx.Issues.First(i => i.IssueID == id); 
     return View(thisIssue); 
    } 

을 다음 HttpPost 동작은 다음과 같이 보입니다 : 멋지고 작동

[HttpPost] 
    public ActionResult Edit(int id, FormCollection form) 
    { 
     // this is the dumb part where I grab the object before I update it. 
     // concurrency is sidestepped here. 
     var thisIssue = edmx.Issues.Single(c => c.IssueID == id); 

     TryUpdateModel(thisIssue); 
     if (ModelState.IsValid) 
     { 
      edmx.SaveChanges(); 

      TempData["message"] = string.Format("Issue #{0} successfully modified.", id); 
      return RedirectToAction("Index"); 
     } 

     return View(thisIssue); 
    } 

합니다. 그러나 동시성 검사가 작동하지 않는 이유는 Post에서 업데이트하기 전에 현재 엔터티를 다시 가져 오기 때문입니다. 그러나 EF를 사용하면 fxiness 인 SaveChanges()을 사용하는 방법을 모르지만 컨텍스트에 내 thisIssue을 첨부합니다. 나는 edmx.Issues.Attach(thisIssue) 전화를 시도했지만 나는

The object cannot be attached because it is already in the object context. An object can only be reattached when it is in an unchanged state. 

을 얻을 어떻게 EF와 MVC에서 동시 처리 및/또는 방법을 상황에 내가 제대로 Attach 내 편집 객체를합니까?

미리 감사드립니다.

답변

6

당신이하고있는 일은 까다 롭지만 일할 수 있습니다. 타임 스탬프 필드가 ConcurrencyToken이라고 가정 해 봅시다. 분명히이 값을보기에 포함시키고 양식과 함께 제출해야합니다. 그러나 POST에서 thisIssue.ConcurrencyToken 값을 단순히 값에 할당 할 수는 없습니다. EF는 "기존"값 (Single()에 대한 호출과 함께 DB에서 가져온 값과 "new"값 모두를 기억하기 때문입니다. .. 양식)와 WHERE 절에 "오래된"값을 사용하면 EF에게 거짓말을하고 올바른 값을 지정해야합니다 그래서이 시도 :

var thisIssue = edmx.Issues.Single(c => c.IssueID == id); 
    TryUpdateModel(thisIssue); // assign ConcurrencyToken 
    var ose = Context.ObjectStateManager.GetObjectStateEntry(entityToUpdate); 
    ose.AcceptChanges();  // pretend object is unchanged 
    TryUpdateModel(thisIssue); // assign rest of properties 

에만 ConcurrencyToken 바인딩 대신 호출하여 최적화 할 수 있습니다 TryUpdateModel 두 번이지만 시작해야합니다.

+0

잘 작동하지만 분명히 느껴집니다. 이것이 내 이슈 객체라고 말하는 방법이 없습니까? 이 문제 객체를 12 번 문제에 첨부하고 12 번 문제를 여기에 저장된 값으로 업데이트 하시겠습니까? 그렇게하면 데이터베이스에 문제 12 번에 동일한 타임 스탬프가 있는지 확인합니다 ... 또한 ConcurrencyToken 필드 만 바인딩하는 방법에 대해 자세히 설명 할 수 있습니까? – Jorin

+0

허용 목록을 전달하여 하나의 입력란 만 바인딩합니다. 거기에 과부하가 있습니다. 업데이트와 관련하여 묻는 것을 수행하려면 스텁 객체를 만들어 컨텍스트에 첨부하고 업데이트하십시오. 이것은 DB로부터 더 새로운'ConcurrencyToken'을 가져 오는 것을 막습니다. –

+0

죄송합니다, 나는 단지 밀도가 있다고 확신합니다.하지만 뭔가를 뽑아 내고 첨부하는 방법에 대해 설명 할 수 있습니까? 나는 이것을 시도하고 작동 didnt는 \t \t [HttpPost] \t \t 공공 ActionResult 편집 (INT 아이디, 호 문제) \t \t { \t \t \t 문제 newIssue = 새로운 문제(); \t \t \t newIssue.IssueID = id; \t \t \t newIssue.EntityKey = new System.Data.EntityKey ("MayflyEntities.Issues", "IssueID", id); \t \t \t edmx.Issues.Attach (newIssue); \t \t \t newIssue = 문제; \t \t \t edmx.SaveChanges(); \t \t – Jorin

4

EF5를 사용하여 낙관적 동시성 호환 업데이트를 수행하는 예는 다음과 같습니다 (이 방법은 reposi tory.) Entity는 Timestamp를 [ConcurrencyCheck]으로 정의한다고 가정한다. 동시성 예외는 DbContext.SaveChanges()을 호출 할 때 발생합니다.

public TEntity Update(TEntity entity) 
{ 
    var attached = this.GetById(entity.Id); 
    if (attached == null) 
    { 
     throw new MvcBootstrapDataException("{0} with Id = {1} does not exist.".F(typeof(TEntity).Description(), entity.Id)); 
    } 

    var entry = this.Context.Entry(attached); 

    // The Timestamp must be in the original values for optimistic concurrency checking to occur. 
    // Otherwise the context knows that the Timestamp has been modified in the context 
    entry.OriginalValues["Timestamp"] = entity.Timestamp; 

    entry.CurrentValues.SetValues(entity); 

    attached.Modified = DateTime.Now; 

    return attached; 
} 
관련 문제