防止添加重复值

时间:2017-10-19 14:50:56

标签: entity-framework

在我的应用程序中,我想与导演分配电影。当然没有必要存储重复的导向器,因此我需要以某种方式防止添加重复的行。

我记得过去和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是否正确编码。你有什么提示吗?

3 个答案:

答案 0 :(得分: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中并使用该目录,而不是仅仅创建一个新目录。

答案 1 :(得分:1)

不幸的是,你这样做的方式总是会导致每个对同一个director对象的引用都有一个新的director行。为什么?因为它们是在三种不同的背景下添加的。

EF仅通过DbContext跟踪对象。 (遗憾的是,可能)不会尝试从该对象的属性中收集关于图形中对象状态的任何信息。因此,第二次使用与第一次导演相同的导演保存Movie时,EF只会看到它对Director一无所知,并继续将其作为新对象添加到图表中同样。调用SaveChanges()时,会将其适当添加到数据库中。

您可以在DbEntry之前查看Director引用的SaveChanges()来观察这种情况,并且每次也会看到Director.Id更改。< / p>

您可以使用一些策略来缓解此行为:

  1. 在一个上下文中添加所有内容。
  2. 添加导演,然后为每部电影添加DirectorId中的Director.Id
  3. 添加导演,为每部电影手动将导演对象的入境状态设置为“未更改”。
  4. 在上下文中,首先执行context.Directors.Find(movie.Director.Id);以确保在添加电影之前导演已经在上下文中。

答案 2 :(得分:0)

  

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

我认为你有三个不同的导演,他们会有不同的身份证。

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

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

DataContext会知道导演,你的三部电影也会一样。

  

我的意思是我无法检查是否已有同名目录,   因为我不是手动添加它们。实体框架正在添加新的   目录,不是我。那么,我该怎么办呢?

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