• EntityFramework Add方法与Attach区别


    EntityFramework Add方法与Attach区别

       一 先发问。

      问题:在使用EF过程中,能否有一个方法可以直接执行传入的SQL语句。纠结的只找到了调用存储过程的方法,难道要SqlHelper.cs?

       二 友情提示

       本文内容参考自MSDN

        三 言归正传

      平时使用MVC 开发时,在CRUD相关的Action当中,都会有在最后调用一句代码:

    db.SaveChanges();// Entities db=new Entities() 
    

      这个方法会根据当前欲操作的实体(Entity)所处的状态(State)与数据库交互。单单从名字上可以看出这个方法是为了“保存改变”,在现实中,一位你好久没见的朋友有可能会这样说:“小王啊,好久没见,你变胖了,是不是赚大钱了,生活安逸喽?”姑且不论你是不是张的长胖了,还是赚大钱了,这里面“胖”就是用来表征你当前所处的状况的一个描述。在命名空间System.Data当中,也有一个描述实体所处状态的枚举类型EntityState:

     // 摘要:
        //     实体对象的状态。
        [Flags]
        public enum EntityState
        {
            // 摘要:
            //     对象存在,但未由对象服务跟踪。在创建实体之后、但将其添加到对象上下文之前,该实体处于此状态。通过调用 System.Data.Objects.ObjectContext.Detach(System.Object)
            //     方法从上下文中移除实体后,或者使用 System.Data.Objects.MergeOption.NoTrackingSystem.Data.Objects.MergeOption
            //     加载实体后,该实体也会处于此状态。
            Detached = 1,
            //
            // 摘要:
            //     自对象加载到上下文中后,或自上次调用 System.Data.Objects.ObjectContext.SaveChanges() 方法后,此对象尚未经过修改。
            Unchanged = 2,
            //
            // 摘要:
            //     对象已添加到对象上下文,但尚未调用 System.Data.Objects.ObjectContext.SaveChanges() 方法。对象是通过调用
            //     System.Data.Objects.ObjectContext.AddObject(System.String,System.Object)
            //     方法添加到对象上下文中的。
            Added = 4,
            //
            // 摘要:
            //     使用 System.Data.Objects.ObjectContext.DeleteObject(System.Object) 方法从对象上下文中删除了对象。
            Deleted = 8,
            //
            // 摘要:
            //     对象已更改,但尚未调用 System.Data.Objects.ObjectContext.SaveChanges() 方法。
            Modified = 16,
        }
    

      这五种状态分别是:Detached-游离;UnChanged-没有变化;Added-添加;Deleted-删除;Modified-编辑。Detached状态下的Entity不会被上下文(context)所捕获(track),比如说下面这种情况下:

     public JsonResult Edit(UserModel source)
            {
                if (this.ModelState.IsValid)
                {
                    User destination = new User();
    
                    UserToEntity(source, destination);
                    destination.ID = source.ID;
                    db.Entry(destination).State = System.Data.EntityState.Modified;
                    db.SaveChanges();
                    return Json(new { isok = true, tip = "修改成功" });
                }
                else
                {
                    return Json(new { isok = false, tip = "添加用户失败" });
                }
            }
    

      在db.Entry(destination)……这句代码执行之前,destination的State状态就是游离。

    除了游离状态,剩下的四种状态均会被上下文所捕获,具体意思也很好理解。

      当SavaChanged()方法执行期间,他会查看当前Entity的EntityState的值,决定是去新增(Added)、修改(Modified)、删除(Deleted)、什么也不做(UnChanged)。

      回到正题,DbContext类的Add()方法的作用就是将一个Entity的State修改为Added,这样在SavaChanged()方法就会将实体新增到数据库当中。而Attach在 微软的中文翻译中是附加,不同于Add方法的添加,她是将一个处于Detached的Entity附加到上下文,而附加到上下文后的这一Entity的State为UnChanged,所以在下面的代码中,需要将obj的State修改为Modified:

    /// <summary>
            /// 更新Entity(注意这里使用的傻瓜式更新,可能性能略低)
            /// </summary>
            /// <param name="model"></param>
            /// <returns></returns>
            public virtual bool Update(T entity)
            {
                var obj = db.Set<T>();//新建一个泛型DbSet
                obj.Attach(entity);//附加到上下文
                db.Entry(entity).State = System.Data.EntityState.Modified;//修改State
                return db.SaveChanges() > 0;
         }
    

      新建的obj Entity因为出于Detached,所以我们需要先附加后修改其EntityState;

      搞清楚这点,完成添加功能的Action 是不是可以这样写呢:

     public virtual bool Add(T entity)
            {
                var obj = db.Set<T>();
                obj.Attach(entity);
                 db.Entry(entity).State = System.Data.EntityState.Added;
                return db.SaveChanges() > 0;
    
            }
    

      同样的,删除的Remove方法也可以不用,转而修改其State为Deleted。

      最后,那就可以用Action完成Add或Update的功能:

    public void InsertOrUpdate(Blog blog)
    {
        using (var context = new BloggingContext())
        {
            context.Entry(blog).State = blog.BlogId == 0 ?
                                       EntityState.Added :
                                       EntityState.Modified;
     
            context.SaveChanges();
        }
    }
    

      以往增加删除都是用一个相同的部分视图加上不同的控制器实现,现在只需要在一个控制器就能实现增加和修改了。

     四 Context

        上下文是一个不太好描述清楚的东东,我是这样简单理解的:有一些方法,在参数中不方便,也不可能获取到的东东(请原谅我这样形容),就可以将其存储在上下文中。比如我这个方法需要知道当前用户是谁,需要知道这次请求来自于哪一个Controller,就可以调用不同的Context获得。在MVC中有很多上下文类,列如这篇博文总结的MVC上下文

  • 相关阅读:
    MyReport:DataGrid的打印和打印预览
    plupload上传插件在SpringMVC中的整合
    tomcat性能调优 大赞
    tomcat 9.0.4 性能调优
    java copy 文件夹
    JProfiler8 远程监控tomcat配置过程
    CentOS7安装Nmon(linux性能监控工具)
    Linux(CentOS)下同时启动两个tomcat
    new Runnable中的 this
    netty4----日志框架的检查
  • 原文地址:https://www.cnblogs.com/grj001/p/12223397.html
Copyright © 2020-2023  润新知