2017-10-19 14 views
1

내 응용 프로그램에서 영화를 감독자에게 지정하려고합니다. 물론 중복 된 디렉터를 저장할 필요가 없으므로 중복 된 행을 추가하지 않아도됩니다.중복 값 추가 방지

1. Get Director Id 
    1a. If director exist return existing director Id 
    1b. If director not exist add new and return added director Id 
2. Add new Movie with directorId assigned. 

난 그냥 Entity Framework을 배우고 내가 그런 식으로이 작업을 수행하지 못할 :

나는 옛날이 sql server와 함께 재미와 그 속임수를 썼는지 기억한다. 내 데이터베이스를 컬렉션으로 보는 방식을 바꿔야합니다. 그래서 MovieDirector을 추가하고 있습니다. 내가 제대로 설명했다 있는지 확실하지 않다, 그래서 나는 코드를 보여주기 위해 더 좋을 거라 생각 :

class Program { 
     static void Main(string[] args) { 
      Movie firstMovie = new Movie() { Name = "Titanic" }; 
      Movie secondMovie = new Movie() { Name = "Pulp Fiction" }; 
      Movie thirdMovie = new Movie() { Name = "Matrix" }; 

      Director director = new Director() { Name = "Warner Bros" }; 

      firstMovie.Director = director; 
      secondMovie.Director = director; 
      thirdMovie.Director = director; 

      Db.AddMovie(firstMovie); 
      Db.AddMovie(secondMovie); 
      Db.AddMovie(thirdMovie); 
     } 
    } 

    public class Movie { 
     public int Id { get; set; } 
     public string Name { get; set; } 

     public int DirectorId { get; set; } 
     [ForeignKey("DirectorId")] 
     public virtual Director Director { get; set; } 
    } 

    public class Director { 
     public int Id { get; set; } 
     public string Name { get; set; } 

     public virtual List<Movie> Movies { get; set; } 

     public Director() { 
      Movies = new List<Movie>(); 
     } 
    } 

    public class Db { 
     public static int AddMovie(Movie movie) { 
      using (var context = new MovieContext()) { 
        context.Movies.Add(movie); 
        context.SaveChanges(); 
        return movie.Id; 
       } 
      } 
    } 

    public class MovieContext : DbContext { 
     public DbSet<Movie> Movies { get; set; } 
     public DbSet<Director> Directories { get; set; } 
    } 

그리고 그 일이 내 데이터베이스에 3 배 같은 Director이 그 이후입니다. 나는 단지 1 명만 가질 것으로 예상 했었습니다. 그러나 어떻게 그것을 성취 할 수 있습니까? Directories을 추가하지 않으려면 어떻게해야하나요? 이미 수동으로 추가하지 않기 때문에 같은 이름의 이미 directory이 있는지 확인 할 수 없습니다. Entity Framework은 새 번호 Directory을 새로 추가합니다. 그래서, 어떻게해야합니까?

내가 처리 한 것은 directorId을 추가하고 엔티티 프레임 워크가 적절한 개체를 할당하도록하는 것입니다.

static void Main(string[] args) { 
      Movie firstMovie = new Movie() { Name = "Titanic" }; 
      Movie secondMovie = new Movie() { Name = "Pulp Fiction" }; 
      Movie thirdMovie = new Movie() { Name = "Matrix" }; 

      Director director = Db.GetDirector("Warner Bros"); 

      firstMovie.DirectorId = director.Id; 
      secondMovie.DirectorId = director.Id; 
      thirdMovie.DirectorId = director.Id; 

      Db.AddMovie(firstMovie); 
      Db.AddMovie(secondMovie); 
      Db.AddMovie(thirdMovie); 
     } 

그리고 그 (이 필요한 경우 및 추가) Director를 반환합니다 나의 새로운 방법

public static Director GetDirector(string directorName) { 
      using (var context = new MovieContext()) { 
       if (context.Directories.Any(x => x.Name == directorName)) 
        return context.Directories.FirstOrDefault(x => x.Name == directorName); 
       else { 
        Director newDirector = new Director() { Name = directorName }; 
        context.Directories.Add(newDirector); 
        context.SaveChanges(); 
        return newDirector; 
       } 
      } 
     } 

그래서 그것을 할 수있는 최선의 방법이있다 : 이것은 내가 main을 변경했습니다 어떻게? 새로운 Director을 추가하는 것이 적절하게 코딩되었는지 확실하지 않습니다. 어떤 조언이 있으십니까?

답변

2

당신이하고있는 방식은 항상 동일한 디렉터 객체에 대한 각 참조에 대해 새로운 디렉터 행을 가져옵니다. 왜? 왜냐하면 그들은 세 가지 다른 맥락에서 추가되기 때문입니다.

EF는 DbContext을 통해서만 개체를 ​​추적합니다. (슬프게도, 어쩌면) 그 객체의 속성으로부터 그래프 안의 객체 상태에 관해 무엇인가를 수집하려고 시도하지 않을 것입니다. 따라서 두 번째로 Movie을 첫 번째 디렉터와 동일한 디렉터로 저장하면 EF는 단순히 Director에 대해 알지 못하고 새로운 개체로 그래프에 추가하기 만합니다. SaveChanges()이 호출되면 데이터베이스에 정식으로 추가됩니다.

당신은이 SaveChanges() 전에 Director 참조 할 수 DbEntry 보면 일어날 볼 수 있습니다, 당신은 또한뿐만 아니라 Director.Id 변화 때마다 나타납니다.

이 동작을 완화하는 데 사용할 수있는 몇 가지 전략이있다 :

  1. 가 하나의 맥락에서 모든 것을 추가합니다.
  2. 감독을 추가 한 다음 각 영화에 대해 DirectorIdDirector.Id에서 설정하십시오.
  3. 감독을 추가하면 각 영화에 대해 감독 객체의 진입 상태가 "변경되지 않음"으로 수동 설정됩니다.
  4. 문맥 상 먼저 영화를 추가하기 전에 감독이 컨텍스트에 있는지 확인하려면 context.Directors.Find(movie.Director.Id);을 수행하십시오.
+0

감사합니다. 두 번째 전략은 나를 위해 가장 합리적인 것 같습니다. – Dawvawd

1

내 데이터베이스에 동일한 디렉터가 3 배 있습니다.

3 명의 다른 감독이 있다고 생각합니다. 다른 ID가 있습니다.

하나의 디렉터 만 갖고 싶다면 그에 관한 DataContext를 알 필요가 있습니다. 어쩌면 AddDirector 메서드를 추가하고 사용하기 전에 디렉터를 데이터베이스에 추가 할 수 있습니다.
그런 다음 당신이 할 때

firstMovie.Director = director; 
secondMovie.Director = director; 
thirdMovie.Director = director; 

DataContext를이 감독을 알게 될 것이다, 당신은 당신의 세 영화 같은이있을 것이다.

나는 수동으로 추가하지 않기 때문에 같은 이름의 디렉토리가 이미 있는지 확인하지 못합니다. . Entity Framework에 새로운 디렉토리가 추가되었습니다. 그래서, 어떻게해야합니까?

Entity Framework의 경우 ID 값이없는 두 명의 이사는 두 명의 다른 임원이됩니다. 같은 디렉터를 사용한다는 것을 알리는 유일한 방법은 ID 값이있는 디렉터를 사용하는 것입니다.
그래서 당신은 할 수 있습니다를
- 이름과 ID를 새 이사 {식 1, 이름 = "워너 브라더스"}로 이사를 만들기
- 데이터베이스에 존재 이사를 사용하여 (엔티티 프레임 워크는 그에 대해 알고 , ID가 있습니다)

+0

나는 그렇게 할 수 없다. 새로운 디렉터를 추가하고이 디렉터를 모든 영화에 마지막으로 할당하면 데이터베이스에 3x 디렉터가 표시됩니다. 작동중인 것은 새로운 디렉터를 추가하는 것이지만 id :'firstMovie.Director.Id = director.Id; '로 할당합니다. 내 질문은 - 왜 내가 참조 할 수 없습니까? – Dawvawd

2

다른 쪽에서 길을 갈 수 있습니다. Director 개체 컬렉션에 Movie 개체를 추가하기 만하면됩니다. 그 후에 Director 개체를 데이터베이스에 저장하면 원하는대로 작동합니다. 만 샘플 코드로

:

Movie firstMovie = new Movie { Name = "Titanic" }; 
Movie secondMovie = new Movie { Name = "Pulp Fiction" }; 
Movie thirdMovie = new Movie { Name = "Matrix" }; 

// here you should take one from data context or create it, if it does not exist 
Director director = new Director { Name = "Warner Bros" }; 

director.Movies.Add(firstMovie); 
director.Movies.Add(secondMovie); 
director.Movies.Add(thirdMovie); 

// add new or update director with new movies 
Db.AddOrUpdateDirector(director); 

그리고 물론, 단지 디렉토리가 이미 데이터 컨텍스트에 존재하고 그 중 하나를 사용하는 경우 확인해야 새로 만들 대신.