none
EF5 code first - problème objets imbriqués RRS feed

  • Question

  • Bonjour,

    Je découvre Entity Framework 5 code first et je me trouve face à un problème lors de l’ajout d’un nouvel objet.

    Modèle :

    J’utilise 2 classes, Projet et Techno avec une relation N – N. Pour un projet j’utilise N technologies ; et une technologie est utilisée dans N projets.

    [DataContract(IsReference = true)]
    [Table("Project")]
    public class Project
        {
            public Project() { }
            [DataMember]
            [Key]
            [Required]
            [Column("Id")]
            public int Id { get; set; }
            [DataMember]
            [Required]
            [Column("Name")]
            public string Name { get; set; }
            [DataMember]
            public virtual List<Techno> Technos { get; set; }
        }
    
    [DataContract(IsReference = true)]
        [Table("Techno")]
        public class Techno
        {
            public Techno() { }
            [DataMember]
            [Key]
            [Required]
            [Column("Id")]
            public int Id { get; set; }
            [DataMember]
            [Column("Name")]
            public string Name { get; set; }
            public virtual List<Project> Projects { get; set; }
        }

    Context :

    public class CarreerModelContext : DbContext
        {
            public CarreerModelContext()
                : base("name=DBCarreer")
            {
                var context = ((IObjectContextAdapter)this).ObjectContext;
                context.ContextOptions.ProxyCreationEnabled = false;
            }
            public DbSet<Project> Projects { get; set; }
            public DbSet<Techno> Technos { get; set; }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                //Permet de ne pas créer la base
                Database.SetInitializer<CarreerModelContext>(null);
                //Déclaration relation N N
                modelBuilder.Entity<Project>().
                    HasMany(c => c.Technos).
                    WithMany(p => p.Projects).
                        Map(
                              m =>
                              {
                                  m.MapLeftKey("Id_Project");
                                  m.MapRightKey("Id_Techno");
                                  m.ToTable("ProjectTechno");
                              });
            }
        }


    Repository : je l’utilise pour la communication avec la BDD

    public class Repository<T> where T : class
        {
            private DbContext _db;
            public Repository(DbContext p_DBContext)
            {
                this._db = p_DBContext;
            }
            public T Add(T p_Item)
            {
                try
                {
                    if (p_Item != null)
                    {
                        this._db.Set<T>().Add(p_Item);
                        this._db.SaveChanges();
                    }
                }
                catch (Exception)
                {
                    p_Item = null;
                    throw;
                }
                return p_Item;
            }
                   
            public List<T> Get(Expression<Func<T, bool>> predicate, List<String> p_IncludeString)
            {
                List<T> items = null;
                try
                {
                    IQueryable<T> req = this._db.Set<T>();
                    if (predicate != null)
                    {
                        req = req.Where<T>(predicate).AsQueryable<T>();
                    }
                    if (p_IncludeString != null)
                    {
                        foreach (string include in p_IncludeString)
                        {
                            req = req.Include(include).AsQueryable<T>();
                        }
                    }
                    items = req.ToList<T>();
                }
                catch (Exception)
                {
                    throw;
                }
                return items;
            }       
        }


    Service Web WCF

    [ServiceContract]
        public interface ICarreer
        {
          
            [OperationContract]
            Project AddProject(Project p_Project);
            [OperationContract]
            List<Techno> GetTechnos();
           
        }
    
    public Project AddProject(Project p_Project)
            {
                try
                {
                    using (CarreerModelContext db = new CarreerModelContext())
                    {
                        Repository<Project> rep = new Repository<Project>(db);
                        return rep.Add(p_Project);
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }
         
            public List<Techno> GetTechnos()
            {
                try
                {
                    using (CarreerModelContext db = new CarreerModelContext())
                    {
                        Repository<Techno> rep = new Repository<Techno>(db);
                        return rep.Get(null, null);
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }


    La partie cliente

    CarreerClient proxy = new CarreerClient();
                //Get all technos
                List<Techno> technologies = proxy.GetTechnos();
                //Create Project
                Project p1 = new Project();
                p1.Name = "Projet 1";
                //Affectation des deux prèmière technologies
                p1.Technos = new List<Techno>();
                p1.Technos.Add(technologies[0]);
                p1.Technos.Add(technologies[1]);
                // Sauvegarde du projet
                proxy.AddProject(p1);


    Problème : Lorsque j’ajoute mon projet, les technologies déjà présentes en base de données sont également ajoutées une autre fois. Je me retrouve avec des doublons en base de données.

    Que dois-je faire afin de résoudre ce problème ?

    • Déplacé Aurel Bera lundi 25 février 2013 12:16 OnTopic
    vendredi 22 février 2013 15:37

Réponses

  • Bonjour,

    J'ai déjà connu un problème quasiment similaire.

    Ma solution a été de ne pas ajouter d'objet complet dans une liste mais uniquement les Id.

    Aussi pouvez vous essayez avec ceci : p1.Technos.Add(new Technologies { Id = technologies[0].Id } ?

    En espérant que ça vous aide


    Mathieu Notin

    • Marqué comme réponse Aurel Bera jeudi 28 février 2013 07:43
    vendredi 22 février 2013 19:18
  • Si fais un "Add" c'est normal que ça les ajoute, jette un coup d'oeil à ce graph (tu es dans le scénario 4 il me semble)

    http://imageshack.us/photo/my-images/6/patternsforsuccesswhena.png/

    Sinon pour ma part quand j'ai une relation N-N (donc j'ai une table intermédiaire en bd), je fais une entité ProjectTechno également avec les prop ProjectId et TechnoId. Puis dans les 2 classes Project et Techno je mettrai une prop List<ProjectTechno> ProjectTechnos (au lieu des prop List<Projects> et List<Technos).

    Ainsi quand tu fais un nouveau Project tu garantis que tous les ProjectTechnos sont forcément nouveaux (vu que ton project est nouveau, ça fait une nouvelle combinaison nouveau projectId  + les technoId existants)

    p1.ProjectTechnos.Add(new ProjectTechno() { ProjectId = p1.ProjectId, TechnoId = technologies[0].TechnoId });


    • Proposé comme réponse desopedr lundi 25 février 2013 15:12
    • Marqué comme réponse Aurel Bera jeudi 28 février 2013 07:43
    lundi 25 février 2013 08:22

Toutes les réponses