Entity Framework:如果允许模型处于非法状态,在某些场景下,记得清空DbContext

背景

之前写过两篇文章介绍模型的合法性:

  1. DDD:关于模型的合法性,Entity.IsValid()合理吗?
  2. .NET:关于数据模型、领域模型和视图模型的一些思考

今天讨论的问题其实是关于“主键映射”的,只是其中还涉及一种决策:“允许模型处于非常状态”。

测试代码

 1         public static void Do()
 2         {
 3             Database.SetInitializer<MyDbContext>(new DropCreateDatabaseAlways<MyDbContext>());
 4 
 5             using (var context = new MyDbContext())
 6             {
 7                 /****************添加一个Note*****************/
 8                 var note = new Note { Name = "合法名字" };
 9                 context.Set<Note>().Add(note);
10                 context.SaveChanges();
11                 /****************添加一个Note*****************/
12 
13                 try
14                 {
15                     /****************让Note处于非法状态*****************/
16                     var firstNote = context.Set<Note>().First();
17                     firstNote.Name = "非法名称";
18                     if (firstNote.Name == "非法名称")
19                     {
20                         throw new InvalidOperationException("非法名称");
21                     }
22                     /****************让Note处于非法状态*****************/
23                 }
24                 catch
25                 {
26                     //这里会出现BUG,显示的还是非法名字。
27                     Console.WriteLine(context.Set<Note>().First().Name);
28 
29                     //清空DbContext以后就对了。
30                     foreach (var entity in context.ChangeTracker.Entries())
31                     {
32                         entity.State = EntityState.Detached;
33                     }
34                     Console.WriteLine(context.Set<Note>().First().Name);
35                 }
36             }
37         }

分析

第一个输出之所以不是期望的结果是因为EntityFramework内置了主键映射模式,内存状态还是处于非法状态,虽然First会导致一次数据库往返。

第二个输出之所以正确是因为清空了主键映射,这样会导致重新用数据库的内容填充主键映射。

结论

出现异常最好终止线程或程序的执行,上边这种BUG是因为使用了一种异常反模式:“把异常作为正常的逻辑处理流程”。

备注

这个错误我犯过,后来的朋友也犯过。

 

posted on 2013-07-19 13:07  幸福框架  阅读(1471)  评论(0编辑  收藏  举报

导航

我要啦免费统计