我真的很努力地把我的项目中的所有东西都与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 -否则它会抛出验证异常,要求在创建时提供一个值
对于child类,我得到了以下内容:
[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; }
}注意,子类有一个对owner类的引用,这是"IDLote“和"Lote”属性,owner类有一个子类实例列表-所以我得到了双向引用-我假设这与问题有某种关系
我得到了一个由VS2012自动生成的控制器和视图,它具有与Lote类相关的读/写功能。我在视图中所做的事情可以描述为:我使用Jquery DataTable来管理子类数据(用户可以在DataTable上添加"N“个实例)。我将Post Button替换为对JS方法的调用,该方法只是从表单和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对象”。我真的觉得这与所有者-孩子类之间的双向引用有关,但仍然不知道到底发生了什么以及如何解决它
我开始觉得在这里真的迷失了。任何关于这方面的想法都将非常感谢。谢谢
发布于 2013-10-29 08:50:22
由于对这个老问题有很多观点,现在我确实有了一些答案,我将它们张贴出来以供参考:
Q-关于键属性的int?类型:A-它根本不需要是一个可以为空的整型。实体可以用一个简单的整型属性作为键来声明,当从视图发送JSon对象返回到某个控制器方法时,这个属性(键)可以用值"0“填充。EF将在持久化对象后立即生成正确的值。
Q-关于导航属性,以及当两个类都没有在关键字上获得值(非零)时如何实现两个类之间的关系:A-要发回的JSon对象可以实现它们之间的精确导航关系。当控制器将发布的数据绑定到它应该接收的模型时,它将“理解”它们的关系,并且一旦生成了键的值,它们将正确地相互引用。
Q-关于delete方法尝试中描述的错误:A-当对象应该与其他对象交互时,这些交互应该被EF以任何方式持久化或“理解”,它们必须已经获得,生成或附加到相同的DBContext。EF依赖于DB上下文来创建此交互的树,因此,当objets不存在于相同的DB上下文中时,不可能构建此树。
https://stackoverflow.com/questions/13344371
复制相似问题