EF 4.1 RC: странный каскад Удалить - PullRequest
4 голосов
/ 23 марта 2011

Я должен признать, что функции EF 4.1 RC Codefirst, DataAnnotations и FluentAPI по-прежнему меня впечатляют.Иногда я действительно не знаю, что я делаю ;-) Пожалуйста, смотрите следующие POCO:

public class Country
{
    [Key]
    public Guid ID { get; set; }

    [Required]
    public virtual Currency Currency { get; set; }
}

public class Currency
{
    [Key]
    public Guid ID { get; set; }

    public virtual ICollection<Country> Countries { get; set; }
}

Общая идея: каждой стране нужна валюта.Но валюту вообще не нужно присваивать стране.

Если вы разрешите EF создать соответствующую базу данных, для соглашения будет установлено значение CASCADE DELETE по соглашению.Другими словами: если вы удаляете валюту, соответствующие страны также удаляются.Но в моем случае это , а не , что я хочу.

Я придумал некоторый код в FluentAPI, чтобы отключить CASCADE DELETE:

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithOptional()
            .WillCascadeOnDelete(false);

Я подумал, что это означает: каждой стране нужна валюта.И этой валюте может быть назначено ноль, одна или несколько стран (необязательно).И всякий раз, когда я удаляю валюту, соответствующие страны (если они есть) НЕ будут каскадно удаляться.

Удивительно, но данный подход все равно будет каскадно удалять страну, если я удаляю соответствующую валюту.Кто-нибудь может сказать мне, что я скучаю?

1 Ответ

5 голосов
/ 23 марта 2011

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

Во-вторых, вашему построителю модели необходимо следующее:

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency) //note optional, not required
            .WithMany(c=>c.Countries)         //define the relationship
            .WillCascadeOnDelete(false);

В-третьих, вам необходимо явно удалить ссылку на удаляемую сущность.от его детей:

 Currency c = context.Currencies.FirstOrDefault();

                c.Countries.Clear(); //these removes the link between child and parent

                context.Currencies.Remove(c);

                context.SaveChanges();

[РЕДАКТИРОВАТЬ] Поскольку я подозреваю, что в переводе что-то потеряно, найдите полный код, который демонстрирует, как будет работать безкадровое удаление.

public class Country{
  [Key]
  public Guid ID { get; set; }

  public virtual Currency Currency { get; set; }
}

public class Currency{
  [Key]
  public Guid ID { get; set; }

  public virtual ICollection<Country> Countries { get; set; }
}


public class MyContext : DbContext{
  public DbSet<Currency> Currencies { get; set; }
  public DbSet<Country> Countries { get; set; }

  protected override void OnModelCreating(DbModelBuilder modelBuilder){
    modelBuilder.Entity<Country>()
     .HasRequired(country => country.Currency)
     .WithMany(currency => currency.Countries)
     .WillCascadeOnDelete(false);
  }
}

class Program{
  static void Main(string[] args){
    Database.DefaultConnectionFactory = new   SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");

    Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());

    using (MyContext context1 = new MyContext()){
      Currency c = new Currency{ID = Guid.NewGuid()};

      context1.Currencies.Add(c);

      c.Countries = new List<Country>();

      c.Countries.Add(new Country{ID = Guid.NewGuid()});

      context1.SaveChanges();
   }

   using (MyContext context2 = new MyContext()){
     Currency c = context2.Currencies.FirstOrDefault();

     context2.Currencies.Remove(c);

     //throws exception due to foreign key constraint
     //The primary key value cannot be deleted 
     //because references to this key still exist.   
     //[ Foreign key constraint name = Country_Currency ]

     context2.SaveChanges();
    }          
  }
}

Вы будетеошибка при сохранении, потому что вы удаляете что-то, что является обязательным внешним ключом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...