我可以重写Dispose来创建一个总是调用SaveChanges的实体类吗?

这是一个相当好的观点,我希望答案是“开始时并不是一个好主意” – 也就是说,如果某人有点放纵,它有一个我感兴趣的点。

型号代码:

public partial class MyEntities : ObjectContext { // the idea is if the object is in a using block, this always gets called? protected override void Dispose(bool disposing) { this.SaveChanges(); base.Dispose(disposing); } } 

客户代码:

 using(var model = new MyEntities()) { // do something // no worry about calling model.SaveChanges() } 

我不确定的问题是:

  1. 处置正确的地方是因为我出于某种原因想到“终结” – 我总是对C#破坏感到困惑。

  2. 在客户端代码中抛出exception的情况下,通常会跳过SaveChanges并且这很好,但是如果我认为这是有效的,那么它总是会调用它。 我应该尝试空捕获吗?

     public partial class MyEntities : ObjectContext { protected override void Dispose(bool disposing) { try { this.SaveChanges(); } catch {} base.Dispose(disposing); } } 

不要这样做。 这是个坏主意。

“Dispose”的目的是提前礼貌地处理非托管资源,以便其他进程可以使用它。 “Dispose”不应该有语义 – 它不应该改变程序的状态或以某种方式被要求。 它应该只做它所说的: 处理资源

你应该在终结者中做到吗? 绝对不是 。 那更糟糕。 终结器可能根本不运行,终结器在另一个线程上运行,即使对象未正确初始化,也可以调用终结器,依此类推。 编写终结器几乎从来都不是正确的事情,如果你确实编写了终结器,它应该只处理一个资源。 终结者不要做任何奇特的事情; 如果你这样做,你几乎肯定会写一个危险的错误和脆弱的程序。

切入这里的正确原则是: 如果出于语义原因需要调用,则强制用户将调用放入代码中。 如果他们忘记这样做,他们会在测试中找到答案。 让用户决定是否将调用置于finally块中是否正确。 不要为他们做出决定; 你可能做错了。

  1. 如果您要执行此操作,请执行此操作。

  2. 这是你不应该这样做的原因之一。