關於Linq to sql的一個更新問題

最新也開始研究linq to sql,但隨着深入,發現無論是國外還是國內文檔還是很少,估計隨後一段時間文檔會多起來。
現在有一個更新問題。
先從Datacontext中得到一個實體丟出去,然後對這個實體進行更新,測試了很長時間沒有發現好的方式。
        public Page SavePage(Page page)
        
{
            DataContext dxt 
= new DataContext("server=.;database=xxx");
            dxt.GetTable
<Page>().Attach(page);
            
            dxt.SubmitChanges();           
            
return page;
        
        }
其中page從丟出去後已經變化了,但SubmitChanges()後沒有更新數據庫。
試了很久都不行,最終採用這樣的方式可以。
        public void SavePage<T>(T obj, Action<T> update) where T:class
        
{
            DataContext dxt 
= new DataContext("server=.;database=giga");
            dxt.GetTable
<T>().Attach(obj);
            
//dxt.GetTable<T>().Attach(obj);
            update(obj);
            dxt.SubmitChanges();
        }

//調用
            dataAccess.Update<Page>(page, delegate(Page p)
            
{
                p.PageTitle 
= "aaa";
            }
);
//dataAccess是上面函數的實例

上面代碼的更新可以成功的。
難道對於一個對象的更新會這麼複雜?大家有沒有更簡單的方法?

posted on 2007-07-31 10:04 Axel 閱讀(1376) 評論(20)  編輯 收藏 所屬分類: linq

Feedback

#1樓  2007-07-31 10:29 木野狐

http://www.codeproject.com/vista/LINQ2.asp   回覆  引用  查看    

#2樓 [樓主] 2007-07-31 10:57 Axel

@木野狐
謝謝回覆!以前就看了這個文章的,文中並沒有給答案。
我的問題主要是這個實例是從不同的層遞交過來的,這個時候原先Datacontext的已經沒有了。
現在網上所有的文檔都是在一個datacontext環境中寫的例子的,但對於分層的應用中必須要用到Attach這個方法把另外一個datacontext產生的實例Attach到當前的datacontext環境中來。
  回覆  引用  查看    

#3樓  2007-07-31 11:29 Boler Guo

Hi Axel,

Did you try dxt.GetTable<Page>().Attach(page, true);   回覆  引用  查看    

#4樓 [樓主] 2007-07-31 11:35 Axel

@Boler Guo
試過。會丟出An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.錯誤。
也就是這個實例丟出去後原先的狀態沒有了。所以我纔用到第二個方法。   回覆  引用  查看    

#5樓  2007-07-31 12:10 宋國安

我想問下,你是怎麼丟出去的?是delete了?還是怎麼了?
如果該實體在數據庫中,不存在了,該用Add方法吧!   回覆  引用  查看    

#6樓 [樓主] 2007-07-31 12:18 Axel

@宋國安
也就是這個實例並不是從同一個datacontext環境中出來的。
這個是分層中常用的。
我先從服務器端Get出來一個實例,遞交給客戶端,這時服務端的datacontext已經不存在了。然後從客戶端返回,這時候必須要重建一個datacontext,那麼這個時候就必須把這個實例Attach到這個datacontext中。
並沒有delete。   回覆  引用  查看    

#7樓 [樓主] 2007-07-31 12:26 Axel

核心問題是,更新不是在同一個Datacontext實例中。
網上所有的例子都是,對象實例從一個datacontext實例中得到,然後對象實例發生變化,再從同一個datacontext實例中去更新,這個太簡單了。只要SubmitChanges就能成功。
現在問題的焦點是,對象實例從一個datacontext實例中得到,但後來這個datacontext不存在了,對象實例到別的層裏去轉了一圈,然後要更新,這時必須要重建一個Datacontext實例,然後這個對象實例附加進來。   回覆  引用  查看    

#8樓  2007-07-31 12:30 Martin Yao [未註冊用戶]

1. Add IsVersion=true to the 'Page' table primary key column mapping attribute. I assume it is PageID. So it should be.
[Column(Storage="_PageID"...., IsVersion=true)]
2. Use dxt.GetTable<Page>().Attach(page, true);

Could you try it again?
  回覆  引用  查看    

#9樓 [樓主] 2007-07-31 12:36 Axel

@Martin Yao
謝謝,哈哈。果然是這樣,先前我沒有理解IsVersion含義,把它加到別的字段中去了。在關鍵字加上這個就好了。
另外我試一下IsVersion加到時間戳字段看看行不行。
  回覆  引用  查看    

#10樓  2007-07-31 12:38 宋國安

我倒,c#組的人都出動了。...

Let me introduce IsVersion.

This file indicates that this file represents a TimeStamp field in Sql Server that is automatically updated each time when the row is changed.

This fields can be used to enable more efficient optimistic concurrency conflict detection.

我感覺問題不在這裏,你好像是webservice?需要序列化。
If you’re using SqlMetal to generate you DataContext then you can choose not to pass in the /pluralize flag.
if you are using OR designer
You can turn off pluralization from Options dialog within VS. It’s under “Database Tools->O/R Designer”.   回覆  引用  查看    

#11樓 [樓主] 2007-07-31 12:43 Axel

@宋國安
謝謝,問題就是An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.錯誤
加上IsVersion就好了。


  回覆  引用  查看    

#12樓  2007-07-31 14:12 jjx

你還沒有碰到關係呢 ,linq to sql 在分佈式環境中處理關係n頭大,莫名的錯誤提示一大堆   回覆  引用  查看    

#13樓 [樓主] 2007-07-31 14:19 Axel

@jjx
是,應用深入後就變得複雜了,所謂問題不少還是缺少相關文檔的原因。有什麼問題大家討論。
我自己通過codesmith寫的生成工具,沒有用vs2008的生成工具,主要是我的關係還不在同一層裏。另外自己定製codesmith模塊要可以更靈活。
我現在在設計的時候儘可能使對象間的關係簡單化,不然就算有加載延遲也是很大的負擔。
現在我在mapping映射時有些猶豫,到底是採用特性還是XML,現在這兩個都支持,但我感覺效率會不一樣,什麼時候測試一下。   回覆  引用  查看    

#14樓  2007-08-01 15:05 R2 [未註冊用戶]

是不是需要在自動生成的代碼裏面加IsVersion的屬性啊,可這樣,如果改動dbml文檔,不就把修改過的代碼覆蓋掉了,似乎不是正解,期待高手解答。   回覆  引用  查看    

#15樓  2007-08-01 15:14 R2 [未註冊用戶]

哦,IsVersion在OR Designer裏面是可以設置,把Time Stamp設置爲true就可以了。   回覆  引用  查看    

#16樓 [樓主] 2007-08-01 15:14 Axel

我加上IsVersion就更成功了。如果是分層的應用,就不能用dbml產生代碼。我是自己通過codesmith維護。   回覆  引用  查看    

#17樓  2007-08-02 15:50 江南白衣

如果是分層的應用,就不能用dbml產生代碼
==========================
此話怎講?   回覆  引用  查看    

#18樓  2007-08-02 22:23 yee [未註冊用戶]

暈死,把isversion加在關鍵字上...
isversion是用來做併發控制的.
不過,解決方法是錯誤的.

唉...無語.   回覆  引用  查看    

#19樓  2007-08-02 22:25 yee [未註冊用戶]

對不起,打錯字了.
應該是這樣解決的.加一個timestamp字段,標識這個字段爲version(isversion)
,問題就解決了.   回覆  引用  查看    

#20樓  2007-09-15 19:27 cokkiy [未註冊用戶]

簡單的問題爲什麼要搞複雜呢?Attach 是你在數據庫裏面已經有了記錄,只是在外面修改了,你需要更新回去,採用Attach.如沒有,請用Add就OK。
DataContext db=new DataContetx();

Page p=db.Pages.Single(p=>p.ID==ModifiedOrNewPage.ID);
if(p!=null)
{
db.Pages.Attach(ModifiedOrNewPage,p);
}

else
db.Pages.Add(ModifiedOrNewPage);
db.SubmitChanges();

這個IsVersion一點關係都沒有。如果有Version字段,更新是效率高一點而已,不同去檢查每個字段了。
  回覆  引用  查看    

 
發佈了35 篇原創文章 · 獲贊 1 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章