实体框架 - 我在编辑复杂的实体时遇到问题

时间:2015-09-09 17:49:47

标签: entity-framework asp.net-mvc-4

插入效果很好。此更新不适用于集合。并且不要给出任何错误。我究竟做错了什么? 在代码中有对规则的简要说明。

      public void EditaModelo(Modelo model)
            {
                try
                {
                    // ProjectResponsible - is an unmapped property. It was used to separate ModeloFuncao between type 2 and type 1 (ProjectResponsible and ProductDevelopment)
                    // ModeloFuncao is a collection within a model where for each function there is a responsibility within the model.
                    // In other words, for each record in the function table shows a field on the screen. The same goes for ProductDevelopment.
                    // When you save the model, there will be incusões, deletions and changes of those responsible.
                    // The IsUpdate property tells whether the record already exists and will be changed.
                    var ModelosToAdd = model.ProjectResponsible.Where(x => !String.IsNullOrWhiteSpace(x.Usuario) && !x.IsUpdate).ToList();
                    List<ModeloFuncao> ModelosToRemove = model.ProjectResponsible.Where(x => String.IsNullOrWhiteSpace(x.Usuario) && x.IsUpdate).ToList();
                    List<ModeloFuncao> ModelosToUpdate = model.ProjectResponsible.Where(x => !String.IsNullOrWhiteSpace(x.Usuario) && x.IsUpdate).ToList();

                    ModelosToAdd.AddRange(model.ProductDevelopment.Where(x => !String.IsNullOrWhiteSpace(x.Usuario) && !x.IsUpdate).ToList()); 
                    ModelosToRemove.AddRange(model.ProductDevelopment.Where(x => String.IsNullOrWhiteSpace(x.Usuario) && x.IsUpdate).ToList());
                    ModelosToUpdate.AddRange(model.ProductDevelopment.Where(x => !String.IsNullOrWhiteSpace(x.Usuario) && x.IsUpdate).ToList());

                    if(ModelosToAdd.Count > 0) context.ModelosFuncoes.AddRange(ModelosToAdd); //Insert is Ok
                    if (ModelosToRemove.Count > 0) context.ModelosFuncoes.RemoveRange(ModelosToRemove); //Not tested
                    if (ModelosToUpdate.Count > 0) ModelosToUpdate.ForEach(x => context.ModelosFuncoes.Attach(x)); //Not working

                    // The ModeloPlanta is a collection in the model table and follow the rules as explained below in ModeloPlantaArea.
                    List<ModeloPlanta> plantasToUpdate = model.ModelosPlantas.ToList();
                    plantasToUpdate.ForEach(x => context.ModelosPlantas.Attach(x));//Not working

            // The ModeloPlantaArea is a collection in the model table. Each model has a number of plants and each plant has a number of areas.
           // Each plant has a responsibility and each area has a responsibility.
           // The screen should display a field for each plant x Responsible  and for each Area x Responsible
           // When you save the model, there will be incusões, deletions and changes of those responsible.
                    List<ModeloPlantaArea> AreasToAdd = model.PlantasArea.Where(x => !String.IsNullOrWhiteSpace(x.UsuarioResponsavel) && !x.IsUpdate).ToList();
                    List<ModeloPlantaArea> AreasToUpdate = model.PlantasArea.Where(x => !String.IsNullOrWhiteSpace(x.UsuarioResponsavel) && x.IsUpdate).ToList();
                    List<ModeloPlantaArea> AreasToRemove = model.PlantasArea.Where(x => String.IsNullOrWhiteSpace(x.UsuarioResponsavel) && x.IsUpdate).ToList();

                    if (AreasToAdd.Count > 0) context.ModelosPlantasArea.AddRange(AreasToAdd);//Insert is Ok
                    if (AreasToUpdate.Count > 0) AreasToUpdate.ForEach(x => context.ModelosPlantasArea.Attach(x));//Not working
                    if (AreasToRemove.Count > 0) context.ModelosPlantasArea.RemoveRange(AreasToRemove);//Not tested

                // When saving Model, need to save (add, delete, change) collections. And if a collection fails, the other must not be saved.
                 // So far this Inclusion OK. The change is not working.                

                   this.Update(model);           
                }
                catch (Exception ex)
                {
                    throw ex;
                }

            }

更新方法:

public void Update(Modelo item, IEnumerable<string> fieldsToUpdate = null)
{
    base.context.Modelos.Attach(item);

    base.UpdateSave(item, fieldsToUpdate);
}

UpdateSave方法:

protected void UpdateSave<TEntity>(TEntity item, IEnumerable<string> fieldsToUpdate) where TEntity : class
{
    var entry = this.context.Entry<TEntity>(item);
    if (fieldsToUpdate == null || fieldsToUpdate.Count() == 0)
        entry.State = System.Data.Entity.EntityState.Modified;
    else
    {
        this.changeFieldsModified<TEntity>(entry, fieldsToUpdate);
    }
    this.Save();
}

保存方法:

protected void Save(bool auditing = true)
{
    try
    {
        this.context.SaveChanges(auditing);
    }
    catch (DbEntityValidationException exception)
    {
        throw new ValidationException(exception);
    }
    catch 
    {
        throw;
    }
}

SaveChanges方法:

public int SaveChanges(bool auditing)
{
    var entriesAdded = new List<DbEntityEntry>();

    // Salva o log dos itens alterados e excluídos.
    if (auditing && base.ChangeTracker.HasChanges())
        foreach (var entry in base.ChangeTracker.Entries())
            switch (entry.State)
            {
                case EntityState.Added:
                    entriesAdded.Add(entry);
                    break;
                case EntityState.Deleted:
                    this.saveEntryOperation(entry, EntityState.Deleted);
                    break;
                case EntityState.Modified:
                    this.saveEntryOperation(entry, EntityState.Modified);
                    break;
            }
    // Realiza a persitência de dados
    int count = base.SaveChanges();

    // Salva o log dos itens adicionados.
    if (auditing && entriesAdded.Count > 0)
        foreach (var entry in entriesAdded)
            this.saveEntryOperation(entry, EntityState.Added);

    this.AuditionContext.SaveChanges();
    return count;
}

1 个答案:

答案 0 :(得分:1)

Attach只是将实体添加到更改跟踪中,但如果您在该点之后实际上没有更改它,则其状态仍为Unchanged。它与附加之前的数据库中的内容不同,这一事实毫无意义。

要表示需要更新实体,您需要将其设置为Modified

db.Entry(entity).State = EntityState.Modified;

如果实体尚未附加,这也会附加它,因此也无需拨打Attach

[费雷拉编辑] 这个提示工作正常。我做了如下修改。

if (ModelosToUpdate.Count > 0)
{
    ModelosToUpdate.ForEach(x => 
    {
        context.ModelosFuncoes.Attach(x);
        var entry = this.context.Entry<ModeloFuncao>(x);
        entry.State = System.Data.Entity.EntityState.Modified
    }); 
}