1. 程式人生 > 其它 >EF中Add()和Attach()兩種新增資料方法的區別

EF中Add()和Attach()兩種新增資料方法的區別

最近在開發一個專案,在實現某個模組資料的插入操作時(底層資料庫的互動採用的是EF),發現無論如何資料都不能插入成功,把資料拷貝出來放到資料庫中執行Sql語句時卻能正確插入,下面給出程式碼片段

 public int InsertWithFundInfo(F_WithFunding_Info withinfo)
        {
            int res = 0;
            using (var context = new RenRenChaoContext())
            {
                context.F_WithFunding_Info.Attach(withinfo);
                return res = context.SaveChanges();
            }
        }
核心也就是兩段程式碼,就是不知道問題出在了哪裡。後來想起EF插入資料還有一個Add方法,於是抱著僥倖的心理試了試,結果竟然成功了。
 public int InsertWithFundInfo(F_WithFunding_Info withinfo)
        {
            int res = 0;
            using (var context = new RenRenChaoContext())
            {
                context.F_WithFunding_Info.Add(withinfo);
                //context.F_WithFunding_Info.Attach(withinfo); return res = context.SaveChanges();
}
在網上搜了一番,發現雖然兩者都可以用來插入資料,不過還是有一些細微的差別。

在講解差別之前,我們先來看下名稱空間下的描述實體所處狀態的列舉型別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,
    }<p></p>
這五種狀態分別是:Detached-遊離;UnChanged-沒有變化;Added-新增;Deleted-刪除;Modified-編輯。Detached狀態下的Entity不會被上下文(context)所捕獲(track)。當SavaChanged()方法執行期間,他會檢視當前Entity的EntityState的值,決定是去新增(Added)、修改(Modified)、刪除(Deleted)、什麼也不做(UnChanged)。

1.Attach()

Attach在 微軟的中文翻譯中是附加,不同於Add方法的新增,她是將一個處於Detached的Entity附加到上下文,而附加到上下文後的這一Entity的State為UnChanged。傳遞到Attach方法的物件必須具有有效的EntityKey值。如果該物件不具有有效的EntityKey值,請使用AttachTo方法指定實體集的名稱。

2、Add()

MSDN的解釋:Add方法將物件將一個物件新增到集合中,新增到EntityCollection並建立兩個物件之間的關係。當源物件附加到ObjectContext例項時,方法也將物件新增到ObjectContext當呼叫SaveChanges時,此操作轉換為插入到資料來源中的操作。

自我理解:ObjectContext類的Add()方法的作用就是將一個Entity的State修改為Added,這樣在SavaChanged()方法就會將實體新增到資料庫當中

這樣,在上面的程式中通過呼叫Attach()方法只能把物件新增到了物件上下文中(此時物件的狀態已經是Unchanged的),執行SaveChange()方法並不能真正新增到資料庫中去。要想真正執行還需要新增一個修改實體狀態的程式碼。

context.ObjectStateManager.ChangeObjectState(withinfo,EntityState.Added);  
呼叫Add()方法時其實已經隱藏了修改實體的狀態為Added的這個操作,執行SaveChange()方法就可以進行新增的操作。

在 Linq to EF 增刪改查這篇文章中新增資料介紹了兩種方法的具體使用有興趣的可以參考一下。


參考文獻:https://msdn.microsoft.com/zh-cn/library/system.data.objects.objectcontext.attach(v=vs.110).aspx

                https://msdn.microsoft.com/zh-cn/library/system.data.objects.objectcontext.addobject(v=vs.110).aspx

                https://msdn.microsoft.com/zh-cn/library/bb351713(v=vs.110).aspx

                http://www.cnblogs.com/Jnw-qianxi/archive/2013/08/15/3260989.html