2013-02-12 3 views
2

Я использую Code First EF 5.0 на> Net 4.0 и I имеет 2 класс:Почему EF оленья кожа обновление навигации свойство

public partial class Kennel 
{ 
    public Kennel() 
    { 
     this.Brands = new List<Brand>(); 
     this.Dogs = new List<Dog>(); 
     this.Breeds = new List<Breed>(); 
     this.Owners = new List<Person>(); 
     this.Name1 = new KennelName(); 
     this.Name2 = new KennelName(); 
    } 

    public int ID { get; set; } 
    public /*DogClub*/int Type { get; set; } 
    public KennelName Name1 { get; set; } 
    public KennelName Name2 { get; set; } 
    public string CertificateNumber { get; set; } 
    public System.DateTime? AssigmentDate { get; set; } 
    public string Folder { get; set; } 
    public string Comment { get; set; } 
    public int StatusID { get; set; } 
    public int? FederationID { get; set; } 
    public int? MainOwnerID { get; set; } 
    public int? MainBreedID { get; set; } 

    public virtual ICollection<Brand> Brands { get; set; } 
    public virtual ICollection<Dog> Dogs { get; set; } 
    public virtual Breed MainBreed { get; set; } 
    public virtual Federation Federation { get; set; } 
    public virtual Status Status { get; set; } 
    public virtual Person MainOwner { get; set; } 
    public virtual ICollection<Breed> Breeds { get; set; } 
    public virtual ICollection<Person> Owners { get; set; } 
} 

public partial class Breed 
{ 
    public Breed() 
    { 
     this.Dogs = new List<Dog>(); 
     this.ExpertKerungs = new List<ExpertKerung>(); 
     this.Hallmarks = new List<Hallmark>(); 
     this.Colors = new List<Color>(); 
     this.ExpertBreeds = new List<ExpertBreed>(); 
     this.Kennels = new List<Kennel>(); 
     this.MainKennels = new List<Kennel>(); 
    } 

    public int ID { get; set; } 
    public string FciNumber { get; set; } 
    public string Name { get; set; } 
    public int BreedGroupID { get; set; } 
    public bool IsKerung { get; set; } 
    public string NameLat { get; set; } 
    public string NativeName { get; set; } 
    public int CountryID { get; set; } 
    public System.DateTime? StandardDate { get; set; } 
    public bool IsCACIB { get; set; } 
    public bool IsWork { get; set; } 

    public virtual BreedGroup BreedGroup { get; set; } 
    public virtual ICollection<Dog> Dogs { get; set; } 
    public virtual ICollection<ExpertKerung> ExpertKerungs { get; set; } 
    public virtual ICollection<Hallmark> Hallmarks { get; set; } 
    public virtual ICollection<Color> Colors { get; set; } 
    public virtual Country Country { get; set; } 
    public virtual ICollection<ExpertBreed> ExpertBreeds { get; set; } 
    public virtual ICollection<Kennel> Kennels { get; set; } 
    public virtual ICollection<Kennel> MainKennels { get; set; } 
} 

и отображение:

public class KennelMap : EntityTypeConfiguration<Kennel> 
{ 
    public KennelMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.ID); 

     // Properties 
     //this.Property(t => t.Name1.Name) 
     // .IsRequired(); 

     //this.Property(t => t.Name1.IntlName) 
     // .IsRequired(); 

     //this.Property(t => t.Name2.Name) 
     // .IsRequired(); 

     //this.Property(t => t.Name2.IntlName) 
     // .IsRequired(); 

     // Table & Column Mappings 
     this.ToTable("Kennels"); 
     this.Property(t => t.ID).HasColumnName("ID"); 
     this.Property(t => t.Type).HasColumnName("Type"); 
     this.Property(t => t.Name1.Name).HasColumnName("Name1_Name"); 
     this.Property(t => t.Name1.IntlName).HasColumnName("Name1_IntlName"); 
     this.Property(t => t.Name1.Type).HasColumnName("Name1_Type"); 
     this.Property(t => t.Name1.Approved).HasColumnName("Name1_Approved"); 
     this.Property(t => t.Name2.Name).HasColumnName("Name2_Name"); 
     this.Property(t => t.Name2.IntlName).HasColumnName("Name2_IntlName"); 
     this.Property(t => t.Name2.Type).HasColumnName("Name2_Type"); 
     this.Property(t => t.Name2.Approved).HasColumnName("Name2_Approved"); 
     this.Property(t => t.CertificateNumber).HasColumnName("CertificateNumber"); 
     this.Property(t => t.AssigmentDate).HasColumnName("AssigmentDate"); 
     this.Property(t => t.Folder).HasColumnName("Folder"); 
     this.Property(t => t.Comment).HasColumnName("Comment"); 
     this.Property(t => t.StatusID).HasColumnName("StatusID"); 
     this.Property(t => t.FederationID).HasColumnName("FederationID"); 
     this.Property(t => t.MainOwnerID).HasColumnName("MainOwnerID"); 

     // Relationships 
     this.HasMany(t => t.Owners) 
       .WithMany(t => t.Kennels) 
       .Map(m => 
         { 
          m.ToTable("OwnerKennel"); 
          m.MapLeftKey("Kennels_ID"); 
          m.MapRightKey("Owners_ID"); 
         }); 

     this.HasOptional(t => t.MainBreed) 
       .WithMany(t => t.MainKennels) 
       .HasForeignKey(d => d.MainBreedID); 
     this.HasOptional(t => t.Federation) 
       .WithMany(t => t.Kennels) 
       .HasForeignKey(d => d.FederationID); 
     this.HasRequired(t => t.Status) 
       .WithMany(t => t.Kennels) 
       .HasForeignKey(d => d.StatusID); 
     this.HasOptional(t => t.MainOwner) 
       .WithMany(t => t.MainKennels) 
       .HasForeignKey(d => d.MainOwnerID) 
       .WillCascadeOnDelete(false); 

    } 
} 

Если я пишу следующий код:

int breedID = 1; // some value 
    Breed br = _kennel.Breeds.FirstOrDefault(t => t.ID == breedID); 
    if (br != null) 
    { 
    _kennel.MainBreed = br; 
    // but: _kennel.MainBreedID != br.ID 
    } 

ИЛИ:

int breedID = 1; // some value 
    Breed br = _kennel.Breeds.FirstOrDefault(t => t.ID == breedID); 
    if (br != null) 
    { 
    _kennel.MainBreedID = breedID; 
    // but: _kennel.MainBreed != br 
    } 

Почему EF не обновляет навигационное свойство? Я установил ProxyCreationEnabled и AutoDetectChangesEnabled, но это не работает.

См другого примера образец код (он точно отражает мой реальный код приложения):

Kennel kennel = ctx.Kennels.Add(ctx.Kennels.Create()); 
kennel.Name1.Name = "Test Kennel"; 
List<Breed> breeds = ctx.Breeds.Include(b => b.BreedGroup).OrderBy(t => t.BreedGroupID).Where(t => t.ID == 755 || t.ID == 772).ToList(); 
foreach (var b in breeds) 
    kennel.Breeds.Add(b); 
if (breeds.Count > 0) 
{ 
    kennel.MainBreed = breeds[0]; 
    foreach (var k in kennel.MainBreed.MainKennels) 
    System.Diagnostics.Debug.WriteLine("MainKennel: " + k.Name1.Name); 
    ctx.ChangeTracker.DetectChanges(); 
    //System.Diagnostics.Debug.WriteLine("MainBreed: " + kennel.MainBreed); 
    System.Diagnostics.Debug.WriteLine("MainBreedID: " + kennel.MainBreedID); 
} 

После вызова DetectChanges всех свойства навигации и коллекции отражают изменения (kennel.MainBreedID! = NULL).

+1

Что вы ожидаете, что это не так? –

+1

Я ожидаю, если я установил _kennel.MainBreedID для breedID, чем свойство навигации обновлено автоматически: _kennel.MainBreed == породы и в коллекции breed.MainKennels будут всплывать порода (без явного вызова context.DetectChanges()). –

ответ

3

Попробуйте сделать все ваши свойства POCO виртуальной, а не только в навигационных свойств. Это позволит EF создавать change tracking proxies вместо ленивых прокси-серверов. Я не тестировал это,, но вы можете получить то поведение, которое ожидаете.

+0

Все свойства навигации виртуальны: public virtual Породы MainBreed {get; задавать; } - например. Я пытался написать публичный виртуальный int? MainBreedID {get; задавать; }, но без какого-либо эффекта. –

+0

Попробуйте создать * все * свойства виртуальные. Это позволяет использовать другой тип прокси-объекта. – Olly

+1

Благодарим вас, после того, как все свойства виртуальны все работают без вызова DetectChanges. Почему эта информация отсутствует на сайте Miscrosoft о EF5.0? –

0

Удалите intialisation коллекций из конструктора

//this.Dogs = new List<Dog>(); 
//this.ExpertKerungs = new List<ExpertKerung>(); 
//this.Hallmarks = new List<Hallmark>(); 
//this.Colors = new List<Color>(); 
//this.ExpertBreeds = new List<ExpertBreed>(); 
//this.Kennels = new List<Kennel>(); 
//this.MainKennels = new List<Kennel>(); 
+0

Если я прокомментирую эти строки, чем получаю исключение NullReferenceException, когда добавляю породу в коллекцию питомников: kennel.Breeds.Add (breed) -> Kennel.Breeds NULL. В этом случае вся коллекция NULL. –

+0

Должна быть проблема с ленивыми прокси-серверами загрузки - то есть они не генерируются. – qujck

+0

Нет, если я смотрю в debuger, я вижу, что тип породы - это {System.Data.Entity.DynamicProxies.Breed_72DF71D740DF290F1FEBC8F98EB0F94B65972B0F2DD559AF5514E6F51240F19F} - это прокси ... –