2017-10-19 94 views
1

在我的应用程序中,我想为导演分配电影。当然,没有必要存储重复的导演,所以我需要防止添加重复的行。防止添加重复值

我记得有昔日乐趣sql server和该诀窍:

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,我不能那样做。我必须改变我作为集合来查看数据库的方式。因此,我将Director添加到Movie。我不知道如果我解释说,正确的,所以我认为这将是更好地展示代码:

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并让实体框架分配适当的对象。这就是我改变main

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; 
       } 
      } 
     } 

所以它是做它的最好方法是什么?我不确定是否添加新的Director是正确的编码。你有什么建议吗?

回答

2

不幸的是,你这样做的方式总是会导致每个引用到相同的导演对象的新导演行。为什么?因为它们被添加到三种不同的环境中。

EF只通过DbContext跟踪对象。它(可能会)(也许)不会试图从该对象的属性中收集关于图中对象状态的任何信息。因此,第二次使用与第一个相同的导演保存Movie时,EF简单地看到它不知道有关该Director的任何内容,并继续将其作为新对象添加到图形中。当调用SaveChanges()时,它会正确添加到数据库中。

,您可以观看由SaveChanges()前看DbEntryDirector参考这一点,而你也将每次看到Director.Id改变。

有你可以用它来缓解这种行为的几个策略:

  1. 在一个单一的情况下添加的一切。
  2. 添加导演,然后为每部电影设置DirectorIdDirector.Id
  3. 添加导演,为每部电影手动设置导演对象的输入状态为“不变”。
  4. 在上下文中,首先执行context.Directors.Find(movie.Director.Id);以确保导演在添加电影前已处于上下文中。
+0

谢谢。第二个策略似乎对我来说是最明智的。 – Dawvawd

1

我在我的数据库中有3个相同的导演。

我想你有三个不同的导演,他们会有不同的ID。

如果你想只有一个导演,你需要让他知道关于他的DataContext。也许你可以添加一个方法AddDirector,并在使用之前将导演添加到数据库。
然后,当你这样做:

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

DataContext的就知道了导演,你将有你的三部电影一样。

我的意思是我不能检查是否已经有相同名称的目录, ,因为我没有手动添加它们。实体框架添加新的 目录,而不是我。那么,我能用它做什么?

对于实体框架,没有ID值的两个董事是两个不同的董事。 要让它知道你想使用同一个导演的唯一方法是使用具有ID值的导演。
因此,您可以:
- 使用一个名称和ID的新董事{ID = 1,名称=“华纳兄弟”}创建您的主管
- 使用数据库中存在的董事(实体框架了解他,他有一个ID)

+0

我不能这样做。当我添加新导演并最终将该导演分配给所有电影时,我会在数据库中获得3个导演。正在工作的是添加新的导演,但是通过id分配:'firstMovie.Director.Id = director.Id;'。我的问题是 - 为什么我不能通过引用来分配? – Dawvawd

2

你可以从另一边走。 只需将Movie对象添加到您的一个Director对象的集合中即可。之后,将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); 

当然和,而不是只建立一个新的,如果目录的datacontext已经存在,并使用一个你应该检查。