Как можно избежать повторяющихся строк во внешней таблице с помощью EF Code First - PullRequest
0 голосов
/ 11 февраля 2019

В моем приложении Movies хранятся в БД.Эти Movies имеют Name и Director.

Хорошо известно, что любой человек с таким же Name, как и другой человек, является тем же лицом.Я хотел бы реализовать это ограничение в приложении.

Моя модель:

public class MovieContext: DbContext
{
    public MovieContext(): base("name=testDB") { }
    public DbSet<Movie> Movies { get; set; }
    public DbSet<Director> Revenues { get; set; }
}

public class Movie
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Director Director { get; set; }
}

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

И мое приложение

static void Main()
{

        Director directorA = new Director()
        {
            Name = "A"
        };


        Movie movie1 = new Movie()
        {
            Name = "foo",
            Director = directorA
        };

        Movie movie2 = new Movie()
        {
            Name = "bar",
            Director = directorA
        };
    using (var context = new MovieContext())
    {
        context.Movies.Add(movie1);
        context.SaveChanges();
    }
    using (var context = new MovieContext())
    {
        context.Movies.Add(movie2);
        context.SaveChanges();
    }
}      

(Я избавляюсь от контекстамежду двумя вставками для имитации двух разных запусков программы).

При выполнении этого в таблице Directors создаются две строки:

Id  Name
1   A
2   A

Поскольку директор 1 и директор 2 имеют одинаковыеимя, это один и тот же человек, и поэтому я предпочел бы иметь одну строку.

Я попытался использовать индекс для этого и изменил мою Director модель:

public class Director
{
    [Key]
    public int Id { get; set; }
    [Index(IsUnique =true), StringLength(30)]
    public string Name { get; set; }
}

Однако, это выбрасывает во время выполнения, так как EF пытается вставить одну и ту же строку дважды.Это явно не правильный способ сделать это.

Как правильно сделать так, чтобы идентичные посторонние объекты имели одинаковый идентификатор при вставке данных в Entity Framework?

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

Обновленный ответ

Затем вы хотите сначала вставить директора в БД.Оператор вставки обновит вашу модель в памяти с помощью сгенерированного идентификатора, а вставки вашего фильма не будут создавать новых режиссеров в БД.

static void Main()
{
    Director directorA = new Director()
    {
        Name = "A"
    };

    using (var context = new MovieContext())
    {
        context.Directors.Add(directorA);
        context.SaveChanges(); // Here the object directorA will be updated with the right ID. So movie inserts wont create a new Director
    }

    Movie movie1 = new Movie()
    {
        Name = "foo",
        Director = directorA
    };

    Movie movie2 = new Movie()
    {
        Name = "bar",
        Director = directorA
    };

    using (var context = new MovieContext())
    {
        context.Movies.Add(movie1);
        context.SaveChanges();
    }
    using (var context = new MovieContext())
    {
        context.Movies.Add(movie2);
        context.SaveChanges();
    }
}  

Вы можете использовать метод AddOrUpdate.Первый параметр - это поле для проверки уникальности.Поэтому, если имя найдено, существующая запись будет обновлена, а если она не существует, будет добавлена ​​новая модель.

using (var context = new MovieContext())
{
    context.Movies.AddOrUpdate(m => m.Name, movie1);
    context.SaveChanges();
}

0 голосов
/ 12 февраля 2019

Правильным способом будет то, что во второй операции вы находите объект директора из контекста context.Directors.FirstOrDefault (d => d.Name == "A") и используете возвращенный объект, чем пытаетесь повторно использовать тот, который вы создали заранее.

0 голосов
/ 11 февраля 2019

Я думаю, что вы описываете только обновление записи.Если директор уже создан под определенным именем, и новый директор создан с тем же именем, это должно ограничить создание, поскольку директор с таким именем уже существует, но если в таблице есть другие столбцы, такие как «электронная почта», то это поле следует обновить, еслидиректор уже выходит?

Если это так, почему бы вам просто не сделать Name первичным ключом таблицы?

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Name{ get; set; }

Зачем нужен идентификатор?

...