2010-06-08 6 views
2

여기에서 많은 질문을 발견했으며 인터넷에서 기사를 읽었지만 문제는 해결하지 못했습니다.Entity Framework - Id가없는 엔티티 업데이트

내 모델 (I가 아닌 모든 필수 속성을 스트라이프)과 같습니다 alt text http://i47.tinypic.com/244p6qh.jpg

매일 정도가 업데이트 될 때 "재생"(정보가 포함 된 XML 파일을 통해).

internal Play ParsePlayInfo(XDocument doc) 
{ 
    Play play = (from p in doc.Descendants("Play") 
    select new Play 
    { 
     Theatre = new Theatre() 
     { 
      //Properties 
     }, 
     //Properties 
     LastUpdate = DateTime.Now 
    }).SingleOrDefault(); 

    var actors = (from a in doc.XPathSelectElement(".//Play//Actors").Nodes() 
    select new Lecturer() 
    { 
     //Properties 
    }); 

    var parts = (from p in doc.XPathSelectElement(".//Play//Parts").Nodes() 
    select new Part() 
    { 
     //Properties 
    }).ToList(); 

    foreach (var item in parts) 
    { 
     play.Parts.Add(item); 
    } 

    var reviews = (from r in doc.XPathSelectElement(".//Play//Reviews").Nodes() 
    select new Review 
    { 
     //Properties 
    }).ToList(); 

    for (int i = 0; i < reviews.Count(); i++) 
    { 
     PlayReviews pR = new PlayReviews() 
     { 
      Review = reviews[i], 
      Play = play, 
      //Properties 
     }; 
     play.PlayReviews.Add(pR); 
    } 
    return play; 
} 

Add()를 통해이 "재생"을 추가하면, 이미 존재하는 경우에도 관계없이 재생의 모든 ChildObject가 삽입됩니다. 기존 항목을 업데이트해야하므로 해당 항목에 대해 수행해야합니다. 여기서 문제는 XML에 ID가 전혀 없다는 것입니다.

지금까지 나는 다음과 같은 옵션이 말할 수 :

  1. 추가/
  2. 구조 조정 내 PlayRepositories에 추가-방법을 자식 개체를 업데이트하고 ParsePlayInfo()를 다시 그래서 수를 모두 하위 항목 먼저 및 을 추가 또는 업데이트 한 다음을 새로 만듭니다. 내가 여기있는 유일한 문제는 내가 ParsePlayInfo이() 나는
  3. 여러 구문 분석 방법을 만들어이 주위 을 일할 수있는, 지속성 무지가되고 싶어 이다 (예를 들어 ParseActors()) 을하고 연주에 할당 내 컨트롤러 (내가 ASP.net MVC를 사용하고 있습니다) 모든 후 구문 분석하고 현재 내가 옵션 1을 구현하고

을 추가했다 - 그러나 그것은 잘못 느낀다.

내가 원하는 것은 데이터베이스에 이미있는 엔티티를 업데이트하고 그렇지 않은 엔티티를 업데이트하는 것입니다. 첨부/추가하기 전에 SaveChanges()를 호출해야합니까? (상대적으로) 쉬운 해결책이 있어야합니다. 누군가가 저를 올바른 방향으로 안내 할 수 있다면 고맙겠습니다.

답변

1

아직 답변이 없으므로 직접 작성하겠습니다.

이상하게 생각하는 사람들을 위해 나는 코드를 지저분 해 보였고 성능은 더 나빠 졌다고 생각한다. 하지만 거기에는 많은 사용자가 없을 것이고이 방법은 밤에 한 번만 호출 될 것입니다. 어쨌든 저는 지금 당장이 방법을 사용합니다.

내가 뭘 했니?

글쎄, 나는 옵션 2와 3

private Play UpdatePlay() 
{ 
    using (RepositoryContext context = new RepositoryContext()) 
    { 
     HttpRequest http = new HttpRequest(); 
     PlayRepository rep = new PlayRepository(context); 

     ActorRepository actRep = new ActorRepository(context); 
    ReviewsRepository revRep = new ReviewsRepository(context); 
     TheatreRepository insRep = new TheatreRepository(context); 
     PartRepository partRep = new PartRepository(context); 

     Parser p = new Parser(); 

     XDocument doc = http.GetPlayInfo(); 

     Theatre theatre = p.ParseTheatreInfo(doc); 
     List<Actor> actors = p.ParseActorInfo(doc); 
     List<PlayReviews> playReviews = p.ParseReviewsInfo(doc); 

     for (int i = 0; i < actors.Count; i++) 
     { 
      actors[i] = actRep.AddOrUpdate(actors[i]); 
     } 
     for (int i = 0; i < playReviews.Count; i++) 
     { 
      playReviews[i].Reviews = revRep.AddOrUpdate(playReviews[i].Reviews); 
     } 

     theatre = insRep.AddOrUpdate(theatre); 

     Play play = p.ParsePlayInfo(doc); 

     List<Part> parts = GetParts(play); 

     for (int i = 0; i < parts.Count; i++) 
     { 
      List<Actor> lec = (List<Actor>)parts[i].Actors; 
      for (int j = 0; j < lec.Count; j++) 
      { 
       lec[j] = actRep.AddOrUpdate(lec[j]); 
      } 

     } 

     play = rep.AddOrUpdate(play); 
     context.LoadProperty(play, o => o.Theatre); 
     context.LoadProperty(play, o => o.Actors); 
     context.LoadProperty(play, o => o.PlayReviewss); 
     context.LoadProperty(play, o => o.Parts); 

     rep.Save(); 

     if (play.Theatre != theatre) 
      play.Theatre = theatre; 

     play = rep.AddParts(parts, play); 

     play = rep.AddActor(actors, play); 

     for (int i = 0; i < playReviews.Count; i++) 
     { 
      playReviews[i].Play = play; 
      playReviews[i] = revRep.AddPlayInformation(playReviews[i]); 
     } 

     rep.Save(); 
     return play; 
    } 
} 

(그리고 보조 노트에, 난 그냥 ... 내가 이전에 내 코드의이 부분을 게시하는 것을 잊었다 실현)

와 함께 갔다 당신이 볼 수 있듯이, 저장()를 두 번 호출되는 - 그리고 AddOrUpdate()에서 진행 뭐죠 당신이 고려할 때 악화 :

public Actor AddOrUpdate(Actor entity) 
{ 
    Actor cur = context.Actors.Where(l => l.Name == entity.Name && l.Last_Name == entity.Last_Name).FirstOrDefault(); 
    if (cur == null) 
    { 
     context.Actors.AddObject(entity); 
     return entity; 
    } 
    else 
    { 
     if (!entity.Mail.IsNullOrEmptyOrWhitespace() && cur.Mail != entity.Mail) 
      cur.Mail = entity.Mail; 
    //there are more of these... 

     return cur; 
    } 
} 

I는이 작업을 수행하는 "권리"방법이라고 믿을 수 없어 . 감정이 잘못되었습니다. 어쩌면 EF 나는 코드의 특정 부분을 테스트하지만 내가 경험 것과 내가 SecondType 10 개 새 항목으로 오게하고하지 않은, 너무 비난

FirstEntityType first = new FirstEntityType(); 
first.Id = 2; 
List<SecondType> list = CreateList(); //Let's say this returns a List with 10 elements 
context.FirstEntityType.AddObject(first); 

for (int i = 0; i < list.Count; i++) 
{ 
    list[i].First = first; 
} 

//just for arguments sake a second for 
for (int i = 0; i < list.Count; i++) 
{ 
    context.SecondType.AddObject(list); 
} 

context.SaveChanges(); 

을하는 것입니다 내가 잘못 아니에요 경우 (11) FirstEntityType에 대한.

왜? EF에는 "이봐, 잠깐만 - 그게 같다"라는 메커니즘이없는 이유는 무엇입니까?

나는 db를 직접 사용하는 것처럼 EF가 작동해야한다고 잘못 생각하고 있습니까? 내 예제에서는 "first"를 추가 했으므로 "first"를 사용할 때마다 참조됩니다. (필자의 예제가 설명대로 작동하기를 바랍니다.

+0

아니요, FirstEntityType에 대해 11 개의 항목이없고 데이터베이스에 하나만 있습니다. 하나의 ObjectContext 내에 있으면 객체를 컨텍스트에 추가 할 때 ID가 보존됩니다. 그러나이 코드를 두 번 실행하면 (새로운 컨텍스트 내에서) 두 번째 FirstEntityType (또는 FirstEntityType.id가 비 자동 증가 기본 키일 때 dababase 예외)을 실제로 얻을 수 있습니다. 그래서 : Entity Framework는 실제로 "그것들은 동일합니다!"라고 말하지만 동일한 id 필드 덕분이 아니라 AddObject가 한 ObjectContext 내에서 객체를 고유하게 식별하는 (임시) EntityKey를 만들었 기 때문입니다. – Slauma

+0

나는 이런 식으로 일을하고 많은 항목으로 끝났기 때문에 나는 여전히 그 코드를 갖고 싶다. 그리고 모든 것이 멋지게 (context) {}를 사용하여 감싸 졌기 때문에 나는 같은 문맥을 사용했다는 것을 확신합니다. 어쩌면이 동작을 일으킨 다른 것이거나 어딘가에서 엉망이 됐을 수도 있습니다. 나는 잠시 후 정말로 좌절했고 그 일을 끝내기를 원했습니다. 시간이 있으면 테스트를 해보겠습니다. 누군가가 그것을 모두 읽어 주셔서 감사합니다. :) –