这个诡异的问题搞了我一天才解决,我用ling to sql 来操作两张表,一张是tb_mail_sender,tb_mail_receiver,tb_mail_receiver.mailid作为外键和tb_mail_sender.id进行一对多关联。我建立实体后两个表分别对应:
CMailSender,CMailReceiver:
我们都看到网络上用于示例的文章都是基于同一个datecontext的,但是在大部分项目中,因为分层的关系,我们要将一个实体在外部修改后传入,然后再进行更新。在这样的情况下,我们需要用attache方法来把这个对象附加到,否则就会得到一个异常大概是说对象是另一个datacontext的。
一般我们的代码:
public bool DeleteMailSender(CMailSender sender)
{
TestdbDataContext db = null;
db = new TestdbDataContext();
db.CMailSenders.Attach(sender, true);
db.CMailSenders.DeleteOnSubmit(sender);
db.SubmitChanges();
return true;
}
在大部分情况下可能不会有问题,但是当我们使用了表的关系之后,问题就产生了,
CMailSender有一个MailReceivers来引用左右的子表的相关数据,CMailReceiver有一个CMailSender来引用父表的一条数据。
这时,我们就能遇到那个最诡异的问题:
An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.
我们想删除父表的一条数据,而且字表没有对应的行,理论上是可行的,但是却出现了这个异常,而且是发生在attache方法中。
同样的方法,当我们想删除子表的一条数据时,同样:
public bool DeleteMailReceiver(CMailReceiver receiver)
{
using (TestdbDataContext db = new TestdbDataContext())
{
StreamWriter sw = new StreamWriter("E:\\test\\testlinq\\webs\\log.txt", true); // Append
db.Log = sw;db.CMailReceivers.Attach(receiver, true);
db.CMailReceivers.DeleteOnSubmit(receiver);
db.SubmitChanges();
sw.Close();
return true;
}
}
一样的出错提示。
我为了这个问题大概浪费了大半天时间,最后我在国外 blog 上找到了解决方法,在attache之前先把关联取消。所以我扩展了那两个实体类,然后创建Detach方法:
public partial class CMailReceiver
{
public void Detach()
{
this._CMailSender = default(EntityRef<CMailSender>);
}
}
public partial class CMailSender
{
public void Detach()
{
this.CMailReceivers = default(EntitySet<CMailReceiver>);
}
}
再来用:
public bool DeleteMailSender(CMailSender sender)
{
TestdbDataContext db = null;
db = new TestdbDataContext();
sender.Detach();//////就是这个
db.CMailSenders.Attach(sender, true);
db.CMailSenders.DeleteOnSubmit(sender);
db.SubmitChanges();
return true;
}
还真的就正常了,好像就是发生在两个对象存在外键关联的情况下会发生这个问题。
我总感觉这样会出现点问题,因为好像取消了关系。