1

好的,这可能是我错了的概念,但无论如何......(MVC3)我有一个带有列表属性的实体。我的 CRUD 视图通过 Ajax 帖子向控制器发送 JSon 表示。一切都很好,除了当我发布该实体的更新时,列表属性根本没有更新。实体的所有简单属性都已更新,但(正如我想象的那样)更新树不包括 List 属性。如何让 EF 了解列表中的这些更改?

这是到目前为止的一些代码:

    [HttpPost]
    public JsonResult Edit(Lote lote)
    {
            //Given the IDs present in lote.Documentos, load the List of Documentos
            if (lote.Documentos != null)
            {
                List<Documento> ldoc = new List<Documento>();
                foreach (var d in lote.Documentos)
                {
                    ldoc.Add(db.Documentos.Find(d.IDDocumento));
                }
                lote.Documentos.Clear();
                foreach (var d in ldoc)
                {
                    lote.Documentos.Add(d);
                }
            }

            //Now, clear all the previous errors
            foreach (var modelValue in ModelState.Values)
            {
                modelValue.Errors.Clear();
            }
            //And re-validate the model
            ValidateModel(lote);

            if (ModelState.IsValid)
            {
                if (lote.IDLote > 0)
                {
                    //Updating
                    db.Entry(lote).State = EntityState.Modified;
                }
                else
                {
                    //Inserting
                    db.Lotes.Add(lote);
                }
                db.SaveChanges();
                CustomMessages.Sucesso(TempData, "Informações salvas com sucesso.", 10000);
                return Json(new { Success = 1, IDProprietario = lote.IDLote, ex = "" });
            }
            else
            {
                return Json(new { Success = 0, ex = "Falha na rotina de armazenamento das informações"});
            }

这些就是类本身:

public class Lote
{
    [Key]
    public int IDLote { get; set; }

    (... lots of properties ...)

    [Display(Name = "Documentos")]
    public List<Documento> Documentos { get; set; }
}


public class Documento
{
    //---=== ATRIBUTOS ===---
    [Key]
    public int IDDocumento { get; set; }

    [Required]
    [MaxLength(60)]
    public string Nome { get; set; }

    public List<Lote> Lotes { get; set; }
}

由于这是一个多对多的关系,我也得到了这个:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove
        <System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();

        modelBuilder.Entity<Lote>()
            .HasMany(t => t.Documentos)
            .WithMany(t => t.Lotes)
            .Map(m =>
            {
                m.ToTable("LoteDocumento");
                m.MapLeftKey("IDLote");
                m.MapRightKey("IDDocumento");
            });
(... and some other stuff)

对此有什么帮助吗?

4

1 回答 1

0

尝试更改此行:

ldoc.Add(db.Documentos.Find(d.IDDocumento));

ldoc.Add(db.Documentos.Include("Lotes").FirstOrDefault(x => x.IDDocumento == d.IDDocumento));

您需要确保您正在更改的关系/对象实际上附加到您当前的数据库上下文。否则实体框架将无法跟踪对它们所做的更改。

此链接根据对象上下文对其进行了解释,但我认为相同的规则适用于 DBcontext。

如果这不起作用,请告诉我,因为我真的在努力更好地理解 EF 的工作方式。

好的,找到了更多有用的链接:

ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象

实体框架和连接池

当您执行时Include("Lotes"),将与您的 Documentos 相关的 lotes 添加到 DBContext。实体框架现在正在跟踪这些对象。在您的代码的更下方,您正在使用这一行将它们重新添加到上下文中,db.Entry(lote).State = EntityState.Modified;无论如何,这是我的猜测。

基于上面的链接,我会尝试重新编写你所拥有的(未编译):

[HttpPost]
public JsonResult Edit(Lote lote)
{
    //get old Lote from DB
    var oldLote = db.Lotes.include("Documentos").FirstOrDefault(x => x.IDLote == lote.IDLote);

    //update
    if(oldLote != null)
    {
        //refresh any other properties that you may have changed on it.
        db.Entry(oldLote).CurrentValues.SetValues(lote);

        //not sure if you will even need this section any more but then you can...
        oldLote.Documentos.Clear();
        foreach (var d in lote.Documentos)
        {
            oldLote.Documentos.Add(db.Documentos.include("Lotes").FirstOrDefault(x => x.IDDocumento == d.IDDocumento));
        }
    }    
    else //add
    {
        //not sure if this will work
        foreach (var d in lote.Documentos)
        {
            db.Entry(d).State = EntityState.Modified;
        }

        db.Lotes.Add(lote);
    }

    //then just save changes.  EF is already tracking all your objects and changes.
    db.SaveChanges();
....
于 2012-12-14T18:32:00.897 回答