2011-02-10 3 views
1

J'essaie de reproduire le même comportement que EntityObject en utilisant CTP5 DBContext pour le suivi des modifications. Considérez les tables Movie et Director. La relation est seulement 1 directeur pour un film et plusieurs films pour chaque réalisateur.EntityFramework CTP5 suivi des modifications

var movie = new Movie(); 
      movie.Name = "ABCD"; 
      ctx.Movies.Add(movie);//ctx.Movies.AddObject(movie); 
      movie.Director = new Director() { Name = "dir1" }; 
      var existingDirector = ctx.Directors.Where(a => a.Name == "dir2").FirstOrDefault(); 
      movie.Director = existingDirector; 
      ctx.SaveChanges(); 

Si je cours en utilisant ce EntityObject, ce code créerait un nouveau directeur « dir1 » que les changements sont suivis. Si je cours ce code en utilisant le générateur DbContext CTP 5, le nouveau directeur "dir1" n'est pas créé. J'ai changé les propriétés pour être virtuel dans les deux objets Movie et Director. Voici le code.

public partial class Director 
{ 
    public Director() 
    { 
     //this.Movies = new HashSet<Movie>(); 
    } 

    // Primitive properties 

    public virtual int DirectorId { get; set; } 
    public virtual string Name { get; set; } 

    // Navigation properties 

    public virtual ICollection<Movie> Movies { get; set; } 

} 
public partial class Movie 
{ 
    public Movie() 
    { 
     //this.Actors = new HashSet<Actor>(); 
    } 

    // Primitive properties 

    public virtual int MovieId { get; set; } 
    public virtual Nullable<int> DirectorId { get; set; } 
    public virtual string Name { get; set; } 

    // Navigation properties 

    public virtual Director Director { get; set; }  
} 

J'ai 3 questions.

  • Est-ce que je manque quelque chose ici? Même si j'ai gardé "virtuel" pour chaque propriété, l'objet n'est pas suivi. Pourquoi?
  • Dois-je écrire une logique de "correction d'association" comme cela a été fait dans les POCO EF4?
  • Si oui, pourquoi le code de correction d'association a-t-il été supprimé dans le générateur DbContext T4?

Répondre

1

Bien sûr, le nouveau directeur ne soit sauvé pas parce que vous avez changé le directeur du nouveau film à un un à un moment donné plus tard existant dans votre code, essayez celui-ci et vous les aurez tous deux enregistrés dans DB:

var movie = new Movie(); 
movie.Name = "ABCD"; 
ctx.Movies.Add(movie); 
movie.Director = new Director() { Name = "dir1" };  
//movie.Director = existingDirector; 
ctx.SaveChanges(); 

Vous pouvez écrire votre propre logique de correction d'association, mais cela prendra soin de garder les extrémités de vos associations synchronisées, et n'a rien à voir avec le code que vous avez montré ici.

La raison pour laquelle votre code enregistre le nouveau directeur dans la base de données lors de l'utilisation d'EntityObjects est due à un concept qui a appelé Relationship Span. L'intervalle de relation définit que le ObjectContext attache automatiquement une entité lorsque vous l'avez joint à une autre entité attachée. Si cet objet détaché est nouveau, quand il est attaché au contexte, son EntityState sera ajouté. Cependant, ce comportement Relation relationnelle n'est pas implémenté même lorsque vous utilisez des proxys POCO (c'est-à-dire que vos propriétés de navigation sont virtuelles).

+0

Le code est bête, mais je voulais montrer une divergence entre les générateurs EntityObject et DbContext T4. Le point est avec le générateur EntityObject le même code (sans commenter la ligne) crée le "dir1" dans db alors que le générateur POCO ou DbContext ne le fait pas. Pourquoi? Qu'est-ce qui s'est passé pour changer le suivi? – Jonna

+0

Veuillez lire ma réponse mise à jour. –

0

Je pense que la raison pour laquelle cela ne fonctionne pas comme vous le souhaitez est que vous créez une instance de la classe Movie elle-même (c'est-à-dire en utilisant le nouvel opérateur) plutôt que le proxy dynamique. La classe Movie elle-même n'a pas intégré le suivi des modifications. Par conséquent, lorsque vous définissez la propriété Director, aucune notification n'est envoyée au DbContext. Même si vous avez ajouté le Movie au DbContext, vous continuez de référencer l'objet original, pas un proxy. Je pense que si vous avez créé l'objet en utilisant DbSet.Create() (http://msdn.microsoft.com/en-us/library/gg696685(v=vs.103).aspx) cela fonctionnerait.

Questions connexes