zoukankan      html  css  js  c++  java
  • 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上下文

  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/grj001/p/12223396.html
Copyright © 2011-2022 走看看