SharePoint 数据迁移解决方案
來源于:http://www.cnblogs.com/jianyus/p/3262613.html
前言:說來慚愧,我們的SharePoint內(nèi)網(wǎng)門戶跑了2年,不堪重負,數(shù)據(jù)量也不是很大,庫有60GB左右,數(shù)據(jù)量幾萬條,總之由于各種原因吧,網(wǎng)站速度非常慢,具體問題研究了很久,也無從解決,所有考慮用Net重新搭網(wǎng)站,進行數(shù)據(jù)遷移,也就帶來了數(shù)據(jù)遷移這個問題。
思路:由于SharePoint的架構和Net有著不一樣的特點,而且SharePoint的數(shù)據(jù)庫設計是不為人所知的(當然我們可以了解一些,但不完全),雖然也是基于Net架構的,但是我們很難做到Sql To Sql的方式。所以,只能考慮服務器端對象模型,插入到數(shù)據(jù)庫中的方式,其間,經(jīng)理給的建議非常合理,就是將SharePoint的數(shù)據(jù)整理好插入中間庫,然后統(tǒng)一插入到新網(wǎng)站數(shù)據(jù)庫中。在后來的實踐中,發(fā)現(xiàn)這一方法對數(shù)據(jù)遷移和檢查,都有著非常好的幫助,避免了很多SharePoint對象模型中出錯,但是不好更正的現(xiàn)象。
中間庫設計:
考慮到原內(nèi)網(wǎng)門戶有列表、文檔庫、圖片庫三種主要類型(特殊列表特殊對待),所以創(chuàng)建了兩個數(shù)據(jù)庫表,分別用來存List和DocLib,同時再創(chuàng)建兩個表Image和Attachment用來存列表正文中的圖片和列表附件(文檔庫文檔當做列表附件)。
一、用來存儲列表內(nèi)容的表?--??TABLE [dbo].[List]
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [ID] [int] IDENTITY(1,1) NOT NULL,--主鍵ID [WebID] [nvarchar](max) NULL,--所在網(wǎng)站的Guid [ListID] [nvarchar](max) NULL,--所在列表的Guid [ListName] [nvarchar](max) NULL,--列表名稱 [ContentType] [nvarchar](max) NULL,--所屬內(nèi)容類型 [ItemID] [nvarchar](max) NULL,-- 列表里面的ID [ApprovalState] [int] NULL,--審批狀態(tài) [Title] [nvarchar](max) NULL,--標題 [SubTitle] [nchar](10) NULL,--副標題 [ItemContent] [nvarchar](max) NULL,--內(nèi)容 [Creator] [nvarchar](max) NULL,--創(chuàng)建者LoginName [CreatorID] [nvarchar](max) NULL,--創(chuàng)建者UserID [DispCreator] [nvarchar](max) NULL,--創(chuàng)建者UserName [Modifier] [nvarchar](max) NULL,--修改者LoginName [ModifierID] [nvarchar](max) NULL,--修改者UserID [DispModifier] [nvarchar](max) NULL,--修改者UserName [CreatTime] [datetime] NULL,--創(chuàng)建時間 [ModifyTime] [datetime] NULL,--修改時間 [TransferDate] [datetime] NULL,--數(shù)據(jù)遷移時間 |
二、用來存儲文檔庫/圖片庫的表?--?TABLE [dbo].[DocLib]
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | [ID] [int] IDENTITY(1,1) NOT NULL,--主鍵ID [WebID] [nvarchar](max) NULL,--所在網(wǎng)站的Guid [ListID] [nvarchar](max) NULL,--所在列表的Guid [ListName] [nvarchar](max) NULL,--列表名稱 [ListType] [nvarchar](max) NULL,--列表類型(文檔庫/圖片庫) [ItemID] [nvarchar](max) NULL,-- 列表里面的ID [ApprovalState] [int] NULL,--審批狀態(tài) [Title] [nvarchar](max) NULL,--標題 [Creator] [nvarchar](max) NULL,--創(chuàng)建者LoginName [CreatorID] [nvarchar](max) NULL,--創(chuàng)建者UserID [DispCreator] [nvarchar](max) NULL,--創(chuàng)建者UserName [Modifier] [nvarchar](max) NULL,--修改者LoginName [ModifierID] [nvarchar](max) NULL,--修改者UserID [DispModifier] [nvarchar](max) NULL,--修改者UserName [CreatTime] [datetime] NULL,--創(chuàng)建時間 [ModifyTime] [datetime] NULL,--修改時間 [Url] [nvarchar](max) NULL,--文檔的Url [TransferDate] [datetime] NULL,--數(shù)據(jù)遷移時間 |
? 三、用來存儲正文圖片的表?--?TABLE [dbo].[Image]
| 1 2 3 4 5 6 7 | [ID] [int] IDENTITY(1,1) NOT NULL,--主鍵ID [WebID] [nvarchar](max) NULL,--所在Web的Guid [WebSubUrl] [nvarchar](max) NULL,--所在Web的相對WebUrl [ListID] [nvarchar](max) NULL,--所在列表的Guid [ListName] [nvarchar](max) NULL,--列表名稱 [ItemID] [nvarchar](max) NULL,-- 列表里面的ID [ImageUrl] [nvarchar](max) NULL,--內(nèi)容圖片的Url,多張圖片,逗號分隔 |
? 四、用來存儲附件集的表?--?TABLE [dbo].[Attachment]
| 1 2 3 4 5 6 7 | [ID] [int] IDENTITY(1,1) NOT NULL,--主鍵ID [WebID] [nvarchar](max) NULL,--所在Web的Guid [WebSubUrl] [nvarchar](max) NULL,--所在Web的相對WebUrl [ListID] [nvarchar](max) NULL,--所在列表的Guid [ListName] [nvarchar](max) NULL--列表名稱 [ItemID] [nvarchar](max) NULL,-- 列表里面的ID [AttachUrl] [nvarchar](max) NULL,--附件的Url,多個的時候,逗號分隔 |
代碼方法段:
首先就是對象模型讀取列表插入List表,然后是對象模型讀取文檔庫/圖片庫插入DocLib表,讀取字段的代碼比較簡單,我們就不過多介紹,就介紹下其間遇到的幾個問題,也避免代碼太多太繁雜。
問題一:正文亂碼
這是一個比較操心的問題,插入數(shù)據(jù)沒有問題,但是到新系統(tǒng)顯示,發(fā)現(xiàn)好多正文帶有雷系”?“之類的東西,這樣子肯定不行,首先想到RePlace,然后想想不太靠譜,因為正文里很有可能有正常的問號,這樣會被替換掉。后來想到可能是編碼問題,后來證實確實是編碼問題,將特別的空格處理替換為 即可,處理如下:
| 1 2 3 4 5 6 | //Content替換空格為 ? byte[] space = new?byte[] { 0xc2, 0xa0 }; string?UTFSpace = System.Text.Encoding.GetEncoding("UTF-8").GetString(space); Content = Content.Replace(UTFSpace, "?"); Content = DeleteHtmlImgTag(Content); Content = Content.Replace("'", "''"); |
問題二 處理中途報錯
插入過程中,我們會出現(xiàn)一些操作異常的情況,可能整個程序要運行4-5個小時,但是4個小時的時候,出現(xiàn)異常了,我們很惱火,調(diào)試也很困難,因為很難去調(diào)試問題,即使把斷點打在Catch里面,調(diào)試也是力不從心的,所以,我們必須一次成功,不容許中間出差錯。這樣,我采取了空跑程序(只走對象模型,不插入數(shù)據(jù)庫,因為Insert很慢,而且?guī)缀醪粓箦e,錯誤多數(shù)出現(xiàn)在對象模型調(diào)用上,各種字段沒有、對象為空)和記錄錯誤補錄兩個方式,來避免這樣的問題。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public?static?void?WriteErrorLog(string?ErrorMessage) { ????try ????{ using?(StreamWriter sw = File.AppendText(@"log_error "?+ InsertTime.ToString("yyyy-MM-dd HHmmss") + ".txt")) { ??? sw.WriteLine(ErrorMessage); ??? sw.Dispose(); } ????} ????catch{ ????} ????Console.WriteLine(ErrorMessage); } |
問題三 處理中間的小錯誤
操作過程中,對于代碼編寫的可靠性,要求很好,就像上面所說,一個要跑4-5個小時的程序,4個小時的時候報錯,我們基本就屬于前功盡棄,因為繼續(xù)插入是很困難的。所以中間的小問題,對于代碼段的可靠性要求,就非常高了。必要的時候,多加一些Try...Catch...可能會對于效率有一點點影響,但是對于整個程序來說,是非常必要的。
| 1 2 3 4 5 6 | if?(!web.Exists){}//判斷web是否存在 list = web.Lists[ListName];//打開的時候Try一下,避免不存在,ListName最好Trim一下 if?(list.BaseTemplate == SPListTemplateType.Announcements)//判斷l(xiāng)ist類型 if?(list.Fields.ContainsField("SubTitle"))//判斷是否有SubTitle這個字段 //副標題對象不為空,才賦值,否則賦值為空字符串(下面那行的注釋…) SubTitle = (item["SubTitle"] == null) ? string.Empty : item["SubTitle"].ToString(); |
問題四 提取正文中的圖片URL
我們數(shù)據(jù)遷移過程,正文中會帶有圖片,這就要求我們把圖片保存下來,遷移過去,然后還要插入到相同的位置。這是個比較讓人頭疼的問題,首先說下邏輯,讀取正文的時候,用正則表達式獲取所有的圖片(不是絕對路徑的要拼成絕對路徑),然后插入到Image中間庫中,將原來圖片的位置,替換為一個圖片標志,因為之后我們還要把圖片插入到這里。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /// <summary> /// 取得HTML中所有圖片的 URL。 /// </summary> /// <param name="sHtmlText">HTML代碼</param> /// <returns>圖片的URL列表</returns> public?static?string[] GetHtmlImageUrlList(string?sHtmlText) { ????// 定義正則表達式用來匹配 img 標簽 ????Regex regImg = new?Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase); ????// 搜索匹配的字符串 ????MatchCollection matches = regImg.Matches(sHtmlText); ????int?i = 0; ????string[] sUrlList = new?string[matches.Count]; ????// 取得匹配項列表 ????foreach?(Match match in?matches) sUrlList[i++] = match.Groups["imgUrl"].Value; ????return?sUrlList; } |
問題五 將正文中的圖片Url換為標識<ImgType>
同樣使用正則表達式,將圖片標簽<img.../>替換為我們特定的標識,為將來replace回來做準備,代碼附下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /// <summary> /// 去處HTML中所有圖片的img標簽。 /// </summary> /// <param name="sHtmlText">HTML代碼</param> /// <returns>去除img標簽后的Html</returns> public?static?string?DeleteHtmlImgTag(string?sHtmlText) { ????string?result = Regex.Replace(sHtmlText, @"<img.*?src=(['""]?)(?<url>[^'"" ]+)(?=\1)[^>]*>", delegate(Match m) ????{ return?"<ImgType>"; ????}); ????if?(result.IndexOf("</img>") > 0) ????{ result = result.Replace("</img>", ""); ????} ????if?(result.IndexOf("</IMG>") > 0) ????{ result = result.Replace("</IMG>", ""); ????} ????return?result; } |
中間庫到新系統(tǒng):
經(jīng)過將SharePoint中數(shù)據(jù),整理插入到中間庫的過程,我們等于已經(jīng)完成80%的工作,因為剩下的內(nèi)容,就是Sql To Sql的問題了,對于net開發(fā)人員,甚至不需要設計,你只需要了解新系統(tǒng)的數(shù)據(jù)庫結構,相應字段插入就可以了。唯一要提到的就是附件/圖片處理的問題,下面我說下我的處理方式:
附件/圖片處理
這也是一個比較棘手的問題,因為眾所周知的原因,SharePoint的附件/圖片是BLOB的形式,存儲在數(shù)據(jù)庫中的(我嘗試去數(shù)據(jù)庫中找這個字段,沒找到);所以我們只能用對象模型,當然SPFile是我們第一時間想到的,但是效率可想而知(效率太慢放棄);所以考慮先將附件/圖片的Url地址拼接好,插入到Images/Attachment的中間庫中,然后采取WebClient的對象去下載為Byte[],然后直接上傳,測試結果還是很客觀的,100個附件1分鐘左右(與附件大小有關)。
| 1 2 3 4 5 6 7 | using?(WebClient wc = new?WebClient()) { ????NetworkCredential networkCredential = new?NetworkCredential("用戶名", "密碼", "域"); ????wc.Credentials = networkCredential; ????byte[] ss = wc.DownloadData(url); ????return?ss; } |
總結:數(shù)據(jù)遷移過程比較繁雜,需要考慮的東西比較多,前期的規(guī)劃很重要,因為數(shù)據(jù)一旦遷移過去,修修補補會很讓人郁悶,所以對應關系一定一定要先做好,避免后期修改。而且,兩邊系統(tǒng)的開發(fā)人員對接非常重要,避免出現(xiàn)少插入字段等現(xiàn)象,造成新系統(tǒng)出問題?;旧暇褪且陨线@些,寫出來給有需要的人們參考下,就這樣了。
?
?
天天想你紅棗,您的健康,‘棗‘的承諾 <a href="http://shop109102900.taobao.com" target="_blank" style="color:red">天天想你紅棗淘寶店</a>
轉載于:https://www.cnblogs.com/TNSSTAR/p/3602811.html
總結
以上是生活随笔為你收集整理的SharePoint 数据迁移解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于WCF中间层服务器端DTO属性更新如
- 下一篇: Ubuntu设置环境变量