问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

SharePoint数据迁移解决方案

发布网友 发布时间:2024-09-25 16:35

我来回答

1个回答

热心网友 时间:2024-10-05 14:41

思路:由于SharePoint的架构和Net有着不一样的特点,而且SharePoint的数据库设计是不为人所知的(当然我们可以了解一些,但不完全),虽然也是基于Net架构的,但是我们很难做到Sql To Sql的方式。所以,只能考虑服务器端对象模型,插入到数据库中的方式,其间,经理给的建议非常合理,就是将SharePoint的数据整理好插入中间库,然后统一插入到新网站数据库中。在后来的实践中,发现这一方法对数据迁移和检查,都有着非常好的帮助,避免了很多SharePoint对象模型中出错,但是不好更正的现象。

  中间库设计:

  考虑到原内网门户有列表、文档库、图片库三种主要类型(特殊列表特殊对待),所以创建了两个数据库表,分别用来存List和DocLib,同时再创建两个表Image和Attachment用来存列表正文中的图片和列表附件(文档库文档当做列表附件)。

  一、用来存储列表内容的表 --  TABLE [dbo].[List]

+ View Code? 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,--所在网站的Guid [ListID] [nvarchar](max) NULL,--所在列表的Guid [ListName] [nvarchar](max) NULL,--列表名称 [ContentType] [nvarchar](max) NULL,--所属内容类型 [ItemID] [nvarchar](max) NULL,-- 列表里面的ID [ApprovalState] [int] NULL,--审批状态 [Title] [nvarchar](max) NULL,--标题 [SubTitle] [nchar](10) NULL,--副标题 [ItemContent] [nvarchar](max) NULL,--内容 [Creator] [nvarchar](max) NULL,--创建者LoginName [CreatorID] [nvarchar](max) NULL,--创建者UserID [DispCreator] [nvarchar](max) NULL,--创建者UserName [Modifier] [nvarchar](max) NULL,--修改者LoginName [ModifierID] [nvarchar](max) NULL,--修改者UserID [DispModifier] [nvarchar](max) NULL,--修改者UserName [CreatTime] [datetime] NULL,--创建时间 [ModifyTime] [datetime] NULL,--修改时间 [TransferDate] [datetime] NULL,--数据迁移时间

  二、用来存储文档库/图片库的表 -- TABLE [dbo].[DocLib]

+ View Code? 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,--所在网站的Guid [ListID] [nvarchar](max) NULL,--所在列表的Guid [ListName] [nvarchar](max) NULL,--列表名称 [ListType] [nvarchar](max) NULL,--列表类型(文档库/图片库) [ItemID] [nvarchar](max) NULL,-- 列表里面的ID [ApprovalState] [int] NULL,--审批状态 [Title] [nvarchar](max) NULL,--标题 [Creator] [nvarchar](max) NULL,--创建者LoginName [CreatorID] [nvarchar](max) NULL,--创建者UserID [DispCreator] [nvarchar](max) NULL,--创建者UserName [Modifier] [nvarchar](max) NULL,--修改者LoginName [ModifierID] [nvarchar](max) NULL,--修改者UserID [DispModifier] [nvarchar](max) NULL,--修改者UserName [CreatTime] [datetime] NULL,--创建时间 [ModifyTime] [datetime] NULL,--修改时间 [Url] [nvarchar](max) NULL,--文档的Url [TransferDate] [datetime] NULL,--数据迁移时间

   三、用来存储正文图片的表 -- TABLE [dbo].[Image]

+ View Code? 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,--内容图片的Url,多张图片,逗号分隔

   四、用来存储附件集的表 -- TABLE [dbo].[Attachment]

+ View Code? 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表,读取字段的代码比较简单,我们就不过多介绍,就介绍下其间遇到的几个问题,也避免代码太多太繁杂。

  问题一:正文乱码

  这是一个比较操心的问题,插入数据没有问题,但是到新系统显示,发现好多正文带有雷系”?“之类的东西,这样子肯定不行,首先想到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("'", "''");

  问题二 处理中途报错

  插入过程中,我们会出现一些操作异常的情况,可能整个程序要运行4-5个小时,但是4个小时的时候,出现异常了,我们很恼火,调试也很困难,因为很难去调试问题,即使把断点打在Catch里面,调试也是力不从心的,所以,我们必须一次成功,不容许中间出差错。这样,我采取了空跑程序(只走对象模型,不插入数据库,因为Insert很慢,而且几乎不报错,错误多数出现在对象模型调用上,各种字段没有、对象为空)和记录错误补录两个方式,来避免这样的问题。

? 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个小时的时候报错,我们基本就属于前功尽弃,因为继续插入是很困难的。所以中间的小问题,对于代码段的可靠性要求,就非常高了。必要的时候,多加一些Try...Catch...可能会对于效率有一点点影响,但是对于整个程序来说,是非常必要的。

? 1 2 3 4 5 6 if (!web.Exists){}//判断web是否存在 list = web.Lists[ListName];//打开的时候Try一下,避免不存在,ListName最好Trim一下 if (list.BaseTemplate == SPListTemplateType.Announcements)//判断list类型 if (list.Fields.ContainsField("SubTitle"))//判断是否有SubTitle这个字段 //副标题对象不为空,才赋值,否则赋值为空字符串(下面那行的注释…) SubTitle = (item["SubTitle"] == null) ? string.Empty : item["SubTitle"].ToString();

  问题四 提取正文中的图片URL

  我们数据迁移过程,正文中会带有图片,这就要求我们把图片保存下来,迁移过去,然后还要插入到相同的位置。这是个比较让人头疼的问题,首先说下逻辑,读取正文的时候,用正则表达式获取所有的图片(不是绝对路径的要拼成绝对路径),然后插入到Image中间库中,将原来图片的位置,替换为一个图片标志,因为之后我们还要把图片插入到这里。

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /// /// 取得HTML中所有图片的 URL。 /// /// HTML代码 /// 图片的URL列表 public static string[] GetHtmlImageUrlList(string sHtmlText) {     // 定义正则表达式用来匹配 img 标签     Regex regImg = new Regex(@"]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?[^\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换为标识

  同样使用正则表达式,将图片标签替换为我们特定的标识,为将来replace回来做准备,代码附下:

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /// /// 去处HTML中所有图片的img标签。 /// /// HTML代码 /// 去除img标签后的Html public static string DeleteHtmlImgTag(string sHtmlText) {     string result = Regex.Replace(sHtmlText, @"[^'"" ]+)(?=\1)[^>]*>", delegate(Match m)     { return "";     });     if (result.IndexOf("") > 0)     { result = result.Replace("", "");     }     if (result.IndexOf("") > 0)     { result = result.Replace("", "");     }     return result; }

  中间库到新系统:

  经过将SharePoint中数据,整理插入到中间库的过程,我们等于已经完成80%的工作,因为剩下的内容,就是Sql To Sql的问题了,对于net开发人员,甚至不需要设计,你只需要了解新系统的数据库结构,相应字段插入就可以了。唯一要提到的就是附件/图片处理的问题,下面我说下我的处理方式:

  附件/图片处理

  这也是一个比较棘手的问题,因为众所周知的原因,SharePoint的附件/图片是BLOB的形式,存储在数据库中的(我尝试去数据库中找这个字段,没找到);所以我们只能用对象模型,当然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; }

  总结:数据迁移过程比较繁杂,需要考虑的东西比较多,前期的规划很重要,因为数据一旦迁移过去,修修补补会很让人郁闷,所以对应关系一定一定要先做好,避免后期修改。而且,两边系统的开发人员对接非常重要,避免出现少插入字段等现象,造成新系统出问题。基本上就是以上这些,写出来给有需要的人们参考下,就这样了。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
秦皇岛润奥森商贸有限公司怎么样? 秦皇岛港务局实业服务公司劳保用品商店怎么样? 秦皇岛市奥尔玛电器有限公司怎么样? 关于消防上的问题,大家帮帮忙! 嘉兴哪里有考消控证 开个家政公司需要多少钱 家政公司加盟好还是自己做好 梦见我想救鸳鸯的预兆 梦见天边有一对鸳鸯 \"崂山茶韵\"报价 王者荣耀 王者点券可以送给好友吗? 被除数除以除数348,余数是十,并且被除数除数商和余数。多合适163,除数... 零零无限注册过商标吗?还有哪些分类可以注册? 如何解决word文档变成写字板的模式? ...由于税务的失误导致企业收了滞纳金,税票已出,不能更改,这样如何做账... 微信抢红包功能被限制了怎么解封 怎么用写字板打开word文件怎么用写字板打开word文件夹 有首日文还是韩文歌旋律有点像BEYOND的AMANI 为什么我快手评论不了了,昨天在一个人的作品下评论了好多,然后到别人的... logitech无线鼠标耗电 商贸公司没运营 一直是0申报 但是由于忘记申报导致逾期 被国税告知罚 ... 求beyond日文版的Amani的下载地址 什么是税票失控票 如何将word文档转换成写字板? 空白通行证为什么不能用英语学习通 劳务派遣公司增值税专用发票的领购和使用规定是什么? ...但是矢量的,我如何才能将小尺寸的图导出时,变大呢? 老凤祥太坑了,30多克的千足金镯子换了一口价14000的硬金手镯,但是我感... 魔兽世界里练联盟战士职业选哪个种族最好? 我的电脑上的WORD文件word文件变成写字板 主播用的麦克风哪个好 我公司10月取得大量的进项税票,但是近几个月没有收入,半年以后才能有收 ... django怎么批量创建用户(2023年最新分享) 两数相除,商为八余数是16被除数,除数,商,余数的和为463求被除数 KUAOLENG注册过商标吗?还有哪些分类可以注册? ...的商是24,余数是12,被除数,除数,商,余数的和是1998,求被除数是多... 佳能MG3080打印机如何清零呢? 电子元件R472是什么管 买了一个一万多的手镯老凤祥的,回来看是足金的,但是和千足金是一样的... 你在哪个场合见过花,有什么特殊意义 雷柏8200p多媒体无线键盘鼠标套装好不好 卫星电话系统分类 哪些场合的花有特殊意义 雷柏8200无线只用鼠标不用键盘能行吗 鲳鱼怎么做鱼肉鲜香入味还没有腥味? 酒精灯的温度? ...果皮,软软的,白色近透明的厚实果肉,味道体甜甜的,有很多籽,是什么水... R472等于多少千欧? 1211灭火器主要用于扑救用于扑灭油类 8.1除1.8商的整数部分不够商1就商 弱弱的问下1211灭火器是什么