EF 4.1 Каскадирование в двух направлениях между объектами с двумя отношениями - PullRequest
0 голосов
/ 29 марта 2012

У меня есть следующие две сущности:

public class Tournament {
    public int TournamentID { get; set; }
    public String Name { get; set; }
    public int? OfficialID { get; set; }

    public virtual Official HeadOfficial { get; set; }

    public virtual ICollection<Official> Officials { get; set; }
}

public class Official {
    public int OfficialID { get; set; }
    public String Surname { get; set; }
    public String FirstName { get; set; }
    public int TournamentID { get; set; }

    public virtual Tournament Tournament { get; set; }
}

В турнире может быть 0..N официальных лиц, и официальный ДОЛЖЕН иметь связанный с ним турнир. Второе отношение состоит в том, что турнир может иметь официальный статус.

Чтобы EF правильно интерпретировал это при создании базы данных, у меня есть следующее:

    protected override void  OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Tournament>()
            .HasOptional(t => t.HeadOfficial)
            .WithMany()
            .HasForeignKey(t => t.OfficialID);

        modelBuilder.Entity<Tournament>()
            .HasMany(t => t.Officials)
            .WithRequired(o => o.Tournament)
            .HasForeignKey(o => o.TournamentID);        
    }

Если я сейчас удалю турнир, все официальные лица, которые были связаны с этим турниром, будут удалены, что я и хочу. Тем не менее, когда я удаляю официальное лицо, которое было назначено главнокомандующим в одном из турниров, удаление не проходит по причине того, что оператор удаления конфликтует с ограничением ссылки в Tournaments.OfficialID.

1 Ответ

1 голос
/ 29 марта 2012

Если я сейчас удалю турнир, все официальные лица, которые были связаны с этот турнир удален, что я и хочу. Тем не менее, когда я удалить должностное лицо, которое было сделано главным должностным лицом в одном из турниры, удаление не проходит, ссылаясь на то, что удаление заявление противоречило ограничению ссылки в Tournaments.OfficialID.

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

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

Я могу только представить, что вы хотите установить ссылку HeadOfficial на null, если чиновник будет удален. Но нет автоматического способа (например, для каскадного удаления). Вы должны запрограммировать такое поведение, например:

using (var ctx = new MyContext())
{
    var officialToDelete = ctx.Officials.Single(o => o.OfficialID == 5);
    var tournaments = ctx.Tournaments.Where(t => t.OfficialID == 5).ToList();

    foreach (var tournament in tournaments)
        tournament.OfficialID = null;

    ctx.Officials.Remove(officialToDelete);

    ctx.SaveChanges();
}

Я считаю, что цикл foreach не является необходимым, потому что EF исправит отношения (= установит внешний ключ в null), когда вы вызовете Remove. (По сути, сам EF выполняет этот цикл внутренне.) Но важно, чтобы турниры загружались в контекст, потому что EF заботится об исправлении этих отношений (только для прикрепленных (= загруженных) объектов), а не о базе данных (в отличие от каскадного удаления ).

...