最近嘗試在sharepoint里面使用EF訪問本地的數據庫,由於sharepoint只能引用.net3.5的程序集,所以就只能使用EF1.1版本了,(吐槽一下:這個版本的EF由於是最早版本,所以不支持調用 存儲過程:-(),下面說下具體遇到的問題吧。
首先了解下MergeOption
是ObjectContext管理查詢返回的實體四種方式,他們分別是:
1.AppendOnly——如果要獲取的實體在上下文里面,就直接從上下文里面取到,如果不在的話就把取出來的實體附加到上下文里面,這個是默認的方式,這種方式的好處就是會首先從內存里面找你要的實體,比較快。
2.NoTracking——上下文不存實體,這種方式就是說每次都從數據庫里面取數據。
3.OverwriteChanges——如果要獲取的實體在上下文中,那么該實體的值會被數據庫的值覆蓋,然后再返回,如果不在的話就把取出來的實體附加到上下文里面。
4.PreserveChanges——如果要獲取的實體在上下文中,那么該實體中被用戶修改的屬性保持不變,其余的屬性用數據庫的值覆蓋,如果不在的話話就把取出來的實體附加到上下文里面。
我遇到的問題
在上下文中構造了一個實體,將該實體標記為添加,該實體的一個流水號字段FlowCode是由數據庫觸發器自動生成的
BasicInfo binfo = new BaicInfo(); //主鍵
; Guid tempGuid=binfo.UIID = GUID.NewGuid();
binfo.Discription= "Test"; binfo.Type=1; ctx.BasicInfoEntities.Add(binfo);
然后ctx.SaveChanges();數據庫觸發器會給該記錄自動生成FlowCode字段,於是就理所當然的想在該上下文中根據主鍵獲取該記錄的FlowCode,
string flowCode=ctx.BasicInfoEntities.Where(x=>x.UIID==tempGuid).FirstOrDefault().FlowCode;
但是奇怪的是取不到這個FlowCode,可是數據庫里面明明這個字段的被觸發器生成了,是有值的啊, 郁悶,:-(,google了一番有所發現,原來在同一上下文中,調用SaveChanges()的時候EF會生成一大堆的SQL到數據庫,數據庫就會咔咔的執行,但是觸發器是是在數據庫里面執行的,所以數據庫並不會通知EF說,你讓我幫你插入一條數據的時候FlowCode字段的值是我用觸發器生成的,這個值是多少多少,然后EF會更新到ObjectStateManger這個Entity對應的Entry里面。此時上下文里面的binfo實體的數據即使不是最新的(相對於數據庫)它狀態是UnChanged,又由於默認的MergeOption是AppendOnly,所以我們再去根據主鍵獲取實體的時候會返回上下文中的實體,這樣一來就當然取不到FlowCode的值了。
解決辦法:重寫MergeOption為NoTracking
方法一:永久設置實體集MergeOption為NoTracking
ctx.BasicInfoEntities.MergeOption = MergeOption.NoTracking;
方法二:只設置該次調用為NoTracking
string flowCode=ctx.BasicInfoEntities.Execute(MergeOption.NoTracking).Where(x=>x.UIID==tempGuid).FirstOrDefault().FlowCode;
這樣就可以告訴EF從數據庫取該實體的數據了,觸發器生成的FLowCode就取出來鳥。