0

我真的很努力将我的项目中的所有内容都与 EF 一起使用,但这确实变得越来越困难,有时它让我怀疑这是否真的是明智之举(依靠 EF 来编写数据库的所有进出)。好吧,我的问题仍然与 1-N 创建/编辑/删除功能有关(应该很简单,对吧?)。

好的,我在这里粘贴一些与我的代码等价的简单代码。

对于实体,我的主要课程为:

[Table("OLIM_LOTE")]
public class Lote
{
    [Key]
    [Column("LOTE_ID_LOTE")]
    public int? IDLote { get; set; }

    [Column("LOTE_TX_OBS")]
    public string Obs {get;set;}

    [Column("LOTE_TX_DOCUMENTO_EXTRA")]
    public string DocumentoExtra { get; set; }

    [NotMapped]
    public List<DocumentoLote> Documentos { get; set; }

    public void LoadLists()
    {
        OlimpiqueDBContext myDbContext = new OlimpiqueDBContext();
        var docs = (from doc in myDbContext.DocumentosLote
                     where doc.IDLote == this.IDLote
                     select doc);
        this.Documentos = docs.ToList<DocumentoLote>();
    }

}

[注意我使用了可为空的 int?for Key - 否则它会抛出我验证异常,要求创建值]

对于儿童班,我得到了这个:

[Table("OLIM_DOCUMENTO_LOTE")]
public class DocumentoLote
{
    [Key]
    [Column("DOLO_ID_DOCUMENTO_LOTE")]
    public int? IDDocumentoLote { get; set; }

    [Column("DOCU_ID_DOCUMENTO")]
    [ForeignKey("Documento")]
    public int IDDocumento { get; set; }

    public virtual Documento Documento { get; set; }

    [Column("LOTE_ID_LOTE")]
    [ForeignKey("Lote")]
    public int IDLote { get; set; }

    public virtual Lote Lote { get; set; }
}

[请注意,子类具有对所有者类的引用,它们是“IDLote”和“Lote”属性,并且所有者类具有子类实例的列表-所以我得到了双向引用-我假设这在某种程度上与问题有关]

我得到了一个由 VS2012 自动生成的控制器和视图,具有与 Lote 类相关的读/写功能。我在 View 中所做的可以描述为:我使用了一个 Jquery DataTable 来管理子类数据(用户可以在 DataTable 上添加“N”个实例)。我将 Post Button 替换为调用 JS 方法,该方法只是从 Form 和 DataTable 中获取所有数据,并将其包装在 JSon 对象中,然后通过 Ajax 将其发送到控制器。

接收它的控制器方法可以简化如下:

    [HttpPost]
    public JsonResult Edit(Lote lote)
    {
        try
        {
            if (ModelState.IsValid) //<< HAVING PROBLEMS HERE... DETAILS BELOW
            {
                if (lote.IDLote.HasValue)
                {
                    //Separete updates/inserts from deletes
                    List<int?> dbDocs = db.DocumentosLote
                                    .Where(dt => dt.IDLote == lote.IDLote)
                                    .Select(dt => dt.IDDocumentoLote)
                                    .ToList();

                    List<int?> postedDocs = lote.Documentos
                        .Select(pt => pt.IDDocumentoLote)
                        .ToList();

                    List<int?> deletedDocs = dbDocs
                        .Except(postedDocs).ToList();

                    //Perform deletes
                    foreach (var delDocId in deletedDocs)
                    {
                        if (delDocId.HasValue)
                        {
                            DocumentoLote delDoc = db.DocumentosLote
                                .Where(dt => dt.IDLote == lote.IDLote && dt.IDDocumentoLote == delDocId)
                                .Single();

                            db.Entry(delDoc).State = EntityState.Deleted;
                        }
                    }

                    //Perform insert and updates
                    foreach (var doc in lote.Documentos)
                    {
                        if (doc.IDDocumentoLote.HasValue)
                        {
                            db.Entry(doc).State = EntityState.Modified;
                        }
                        else
                        {
                            db.Entry(doc).State = EntityState.Added;
                            doc.IDLote = (int)lote.IDLote;
                        }
                    }
                }
                else
                {
                    db.Lotes.Add(lote);
                }
                db.SaveChanges();

                // If Sucess== 1 then Save/Update Successfull else there it has Exception
                return Json(new { Success = 1, ex = "" });
            }
            else
            {
                return Json(new { Success = 0, ex = "Falha ao tentar salvar os dados" });
            }
        }
        catch (Exception ex)
        {
            // If Sucess== 0 then Unable to perform Save/Update Operation and send Exception to View as JSON
            return Json(new { Success = 0, ex = ex.Message.ToString() });
        }
    }

问题:嗯,我真的经历了很多,现在,我只遇到了两个问题。首先是创建抛出了一个验证异常,说它需要一个 IDLote(对于子类 - 但无论如何,如果所有者类本身在创建时仍然没有 Id,我将如何拥有它?)第二个问题:删除根本不起作用!不管我如何编码,它都会引发异常“无法定义对象,因为它们附加到不同的 ObjectContext 对象”。我真的觉得这与所有者子类之间的双向引用有关,但是仍然不知道到底发生了什么以及如何解决它

我开始觉得这里真的很失落。对此的任何想法将不胜感激。谢谢

4

1 回答 1

0

由于对这个老问题有很多看法,现在我确实有一些答案,所以我将它们发布以供参考:

Q - 关于int?关键属性的类型: A - 它根本不必是可为空的 int。实体可以用一个简单的 int 属性声明为键,当从 View 发布 JSon 对象时,返回到某个控制器方法,该属性(键)可以用值“0”填充。EF 将在持久化对象后立即生成正确的值。

Q - 关于导航属性以及当两个类都没有在 this 键上获得值(非零)时如何实现它们之间的关系: A - 要返回的 JSon 对象可以实现精确的导航关系他们。Wehn 控制器将发布的数据绑定到它应该接收的模型,它将“理解”它们的关系,并且一旦生成键的值,它们就会正确地相互引用。

Q - 关于 delete 方法尝试中描述的错误: A - 当对象应该与其他对象交互,并且这些交互应该由 EF 以任何方式持久化或“理解”时,它们必须已经获得、生成或附加到相同的数据库上下文。EF 依赖 DB 上下文来创建此交互的树,因此,当对象不存在于同一 DB 上下文中时,无法构建此树。

于 2013-10-29T00:50:21.587 回答