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,
    }
View Code

  這五種狀態分別是: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上下文

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM