• 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是因为使用了一种异常反模式:“把异常作为正常的逻辑处理流程”。

    备注

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

  • 相关阅读:
    Eureka 服务的注册和发现
    springcloud 中文文档
    mysql 7 种 join
    通用 mapper
    docker 容器操作( 以 tomcat 为例 )
    linux下安装phpunit简单方法
    图片优化的几个小工具
    安装基准测试工具sysbench
    安装pcntl以实现php多进程
    安装memcache及php的memcached模块
  • 原文地址:https://www.cnblogs.com/happyframework/p/3200360.html
Copyright © 2020-2023  润新知