2017-06-01 1 views
1

C'est la première fois que j'utilise EF dans une application asp.net mvc. Au cours des deux derniers jours, je lis des questions et des exemples semblables, mais jusqu'à maintenant, je n'ai pas compris exactement ce que je devais faire.EF: mise à jour d'une entité avec des entités enfants ajoutées, supprimées ou non (relation plusieurs à plusieurs)

J'ai deux entités avec des relations plusieurs à plusieurs.

Modèle:

[Table("Unit")] 
public class UnitEntity 
{ 
    [Required] 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    [Required] 
    public UnitType Type { get; set; } 

    [StringLength(255)] 
    public string Title { get; set; } 

    ///some other properties 

    public virtual ICollection<UserEntity> Users { get; set; } 
} 

[Table("User")] 
public class UserEntity 
{ 
    [StringLength(255)] 
    public string Id { get; set; } 

    [Required] 
    public string UserName { get; set; } 

    [Required] 
    public string Email { get; set; } 


    public int Status { get; set; } 

    // some other properties 

    public virtual ICollection<UnitEntity> DepartmentUnits { get; set; } 
} 

Et dans mon dbcontext:

public virtual DbSet<UnitEntity> Units { get; set; } 
public virtual DbSet<UserEntity> Users { get; set; } 

modelBuilder.Entity<UserEntity>() 
      .HasMany(e => e.DepartmentUnits) 
      .WithMany(e => e.Users) 
      .Map(m => m.ToTable("UserDepartments").MapLeftKey("UserId").MapRightKey("DepartmentId")); 

La liste des DepartmentUnits pour chaque utilisateur sont mis à jour dans une vue à l'aide d'une liste Multiselect et transmis au contrôleur.

méthode Contrôleur:

[HttpPost] 
    public ActionResult UpdateUser(ExternalUserDTO userdata) 
    { 
     //list of UnitDepartments from the view 
     var userDepartments = new List<UnitEntity>(); 
     foreach (var unitid in userdata.DepartmentIds) 
     { 
      userDepartments.Add(manager.GetUnit(unitid)); 
     } 


     //create new user with data to update 
     UserEntity userentity = new UserEntity() 
     { 
      Id = userdata.Id, 
      DepartmentUnits = userDepartments, 
      Status = userdata.Status 

     }; 


     userManager.UpdateUser(userentity); 

     return new JsonResult { Data = new { Success = false } }; 
    } 

Et en classe UserManager:

public void UpdateUser(UserEntity entity) 
    { 
     var updentity = this.dataContext.Users.Find(entity.Id); 

     if (updentity == null) 
      throw new NullReferenceException("User not found"); 


     updentity.Status = entity.Status; 

     var newUnitIds = entity.DepartmentUnits.Select(u => u.Id); 
     var existingUnitIds = updentity.DepartmentUnits.Select(u => u.Id); 

     updentity.DepartmentUnits.Where(u => !newUnitIds.Contains(u.Id)).ToList().ForEach(d => updentity.DepartmentUnits.Remove(d)); 
     entity.DepartmentUnits.Where(u => newUnitIds.Except(existingUnitIds).Contains(u.Id)).ToList().ForEach(d => updentity.DepartmentUnits.Add(d)); 


     this.dataContext.Entry(updentity).State = EntityState.Modified; 


     foreach (var deptentity in updentity.DepartmentUnits) 
     { 
      if(newUnitIds.Contains(deptentity.Id)) 
      { 
       this.dataContext.Entry(deptentity).State = EntityState.Added; 
      } 
      if(existingUnitIds.Contains(deptentity.Id)) 
      { 
       this.dataContext.Entry(deptentity).State = EntityState.Unchanged; 
      } 
     } 


     try 
     { 
      this.dataContext.SaveChanges(); 

     } 
     catch (Exception) 
     { 
      throw new Exception("Update problem"); 
     } 

    } 

Je dois mettre à jour ma table UserDepartments (voir constructeur de modèle ci-dessus), afin de supprimer enlevé, ajouter de nouvelles et de conserver DepartmentUnits existants pour l'utilisateur spécifique. Ce qui précède ne fonctionne pas, je suis perdu et j'apprécie toute aide.

Répondre

1

Dès que la durée de vie variable de dataContext est scope pour une opération UpdateUser unique, vous pouvez laisser tracker EF changement font le plus gros du travail pour vous en chargeant l'entité cible de la base de données, y compris la collection en question , puis remplacez simplement une liste d'entités stub créée à partir de la collection correspondante de l'entité passée:

public void UpdateUser(UserEntity entity) 
{ 
    // Load the exiting entity from the db, including the collection 
    var dbEntity = this.dataContext.Users 
     .Include(e => e.DepartmentUnits) 
     .FirstOrDefault(e => e.Id == entity.Id); 

    if (dbEntity == null) 
     throw new NullReferenceException("User not found"); 

    // Update the master information 
    this.dataContext.Entry(dbEntity).CurrentValues.SetValues(entity); 

    // Replace the collection with stubs created from the source collection 
    dbEntity.DepartmentUnits = entity.DepartmentUnits.Select(e => new UnitEntity { Id = e.Id }).ToList(); 

    // And that's all - EF change tracker will detect added/removed/unchanged links (and changed master properties) for you. 
    // Just commit the changes and you are done. 
    this.dataContext.SaveChanges(); 
} 

S'il vous plaît noter que cela fonctionne dans EF6. EF Core nécessite actuellement plus de travail manuel similaire à ce que vous avez essayé.

+0

FWIW, cette ligne: '.CurrentValues.SetValues ​​this.dataContext.Entry (dbEntity) (entité),' émet une exception sur les entités étant dans un contexte différent. Cette ligne: 'dbEntity.DepartmentUnits = entity.DepartmentUnits.Select (e => new UnitEntity {Id = e.Id}). ToList();' ajoute une nouvelle ligne dans la table Unit avec des valeurs nulles et ajoute une entrée à la table UserDepartments avec un UnitId qui n'existe pas réellement. Néanmoins, vous avez résolu mon problème parce que vous m'avez fait réfléchir d'une autre manière. Merci beaucoup, je vais mettre ma solution de travail ci-dessous. – tz2015

0

Code de travail:

public void UpdateUser(UserEntity entity) 
    { 

     var updentity = this.dataContext.Users.Include(e => e.DepartmentUnits).FirstOrDefault(e => e.Id == entity.Id); 


     if (updentity == null) 
      throw new NullReferenceException("User not found"); 


     updentity.Status = entity.Status; 

     updentity.DepartmentUnits = entity.DepartmentUnits.Select(e => this.dataContext.Units.Find(e.Id)).ToList(); 


     try 
     { 
      this.dataContext.SaveChanges(); 

     } 
     catch (Exception) 
     { 
      throw new Exception("Update problem");