SharePoint 数据迁移解决方案
来源于:http://www.cnblogs.com/jianyus/p/3262613.html
前言:说来惭愧,我们的SharePoint内网门户跑了2年,不堪重负,数据量也不是很大,库有60GB左右,数据量几万条,总之由于各种原因吧,网站速度非常慢,具体问题研究了很久,也无从解决,所有考虑用Net重新搭网站,进行数据迁移,也就带来了数据迁移这个问题。
思路:由于SharePoint的架构和Net有着不一样的特点,而且SharePoint的数据库设计是不为人所知的(当然我们可以了解一些,但不完全),虽然也是基于Net架构的,但是我们很难做到Sql To Sql的方式。所以,只能考虑服务器端对象模型,插入到数据库中的方式,其间,经理给的建议非常合理,就是将SharePoint的数据整理好插入中间库,然后统一插入到新网站数据库中。在后来的实践中,发现这一方法对数据迁移和检查,都有着非常好的帮助,避免了很多SharePoint对象模型中出错,但是不好更正的现象。
中间库设计:
考虑到原内网门户有列表、文档库、图片库三种主要类型(特殊列表特殊对待),所以创建了两个数据库表,分别用来存List和DocLib,同时再创建两个表Image和Attachment用来存列表正文中的图片和列表附件(文档库文档当做列表附件)。
一、用来存储列表内容的表 -- 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,--所在网站的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]
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]
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]
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
|
/// <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;
}
|
中间库到新系统:
经过将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;
}
|
总结:数据迁移过程比较繁杂,需要考虑的东西比较多,前期的规划很重要,因为数据一旦迁移过去,修修补补会很让人郁闷,所以对应关系一定一定要先做好,避免后期修改。而且,两边系统的开发人员对接非常重要,避免出现少插入字段等现象,造成新系统出问题。基本上就是以上这些,写出来给有需要的人们参考下,就这样了。
天天想你红枣,您的健康,‘枣‘的承诺 <a href="http://shop109102900.taobao.com" target="_blank" style="color:red">天天想你红枣淘宝店</a>
转载于:https://www.cnblogs.com/TNSSTAR/p/3602811.html
SharePoint 数据迁移解决方案相关推荐
- HDFS数据迁移解决方案之DistCp工具的巧妙使用
HDFS数据迁移解决方案之DistCp工具的巧妙使用 参考文章: (1)HDFS数据迁移解决方案之DistCp工具的巧妙使用 (2)https://www.cnblogs.com/felixzh/p/ ...
- Hadoop数据迁移解决方案 上
Hadoop数据迁移解决方案 数据迁移场景 冷热集群数据同步.分类存储 集群数据整体迁移 数据的准时同步 数据迁移考虑的因素 Bandwidth-带宽 带宽用多会影响到线上业务的任务运行,带宽用的少会 ...
- oracle 数据库数据迁移解决方案
大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移,接下来把心得与大家分享一下 去年年底做了不少系统的数据迁移,大部分系统由于平台和版本的原因,做的是逻辑迁移,少部分做的是物理迁移, ...
- 电脑知识:新电脑数据迁移解决方案,看完你就会了!
今天小编给大家分享几种比较实用的电脑数据迁移的方案,希望对大家能有所帮助! 一.将旧电脑硬盘拆下安装到新电脑上 这是最简单粗暴的办法,虽粗暴,可直接有效啊!特别适合要转移数据量特大的,因为我们都知道硬 ...
- SharePoint On Premise 数据迁移到 SharePoint Online的几点考虑
最近在给一个客户做SharePoint数据迁移的项目,从SharePoint 2007到SharePoint Online, 在给客户做计划的时候,着重考虑了两个系统之间的差异和客户对本地系统的自定制 ...
- sap服务器迁移性能问题,专家详解SAP数据迁移的六个方法
[IT168现场报道] 以"蕴韬略 促转变"为主题的SAP商业同略会暨SAP全球技术研发者大会(以下简称大会)于2011年11月15~17日在北京国家会议中心召开. 在SAP全球技 ...
- 【强大的数据迁移和恢复解决方案】KernelApps及其产品介绍
KernelApps是 范围广泛的强大的数据迁移和 恢复解决方案 可以根据用户的需求提供多种采购方案 KernelApps提供 交换服务器.Office 365. 电子邮件迁移.Outlook等方面工 ...
- 我在MongoDB年终大会上获二等奖文章:由数据迁移至MongoDB导致的数据不一致问题及解决方案...
作者 | 上海小胖 来源 | Python专栏(ID:xpchuiit) 故事背景 企业现状 2019年年初,我接到了一个神秘电话,电话那头竟然准确的说出了我的昵称:上海小胖. 我想这事情不简单,就回 ...
- ecs服务器数据迁移_某国际物流集团的云迁移解决方案
新钛云服已为您服务905天 云计算流行当下,使用新技术较早的互联网企业,已基本实现云计算实施.传统企业也开始接触云计算并进行使用,但由于与互联网轻实体资产的模式不同,其往往面临着业务迁移上云的难题.云 ...
最新文章
- 大理,风花雪月俏丽金花
- 计算机排版高级理论知识试卷,2017年9月计算机二级考试《MS Office高级应用》操作题强化提分卷(1)...
- 人工神经网络之BP神经网络模型
- java lambda使用_在Java 8 Lambda上使用Apache Commons Functor功能接口
- [转]Some Cool Tips for .NET
- android自定义拱形,Android自定义View实现圆弧进度的效果
- C#之生成树形菜单数据
- linux dx游戏,10大免费 Linux 游戏
- (JZ1619)2018.07.08【2018提高组】模拟C组 0	.音乐节拍
- Vue routers
- 高数不定积分方法汇总:
- On-Demand Resources Guide中文版(按需加载资源--下)
- 【STM32】OLED显示程序
- 宅家羊毛党是怎么做到月入上万的
- 【雕爷学编程】Arduino动手做(42)---PM2.5粉尘传感器
- 钟汉良日记:你知道吗?写日记可以影响三代人!
- 最大疯子树-树形dp+换根+二次扫描
- 荣耀路由pro没有虚拟服务器,荣耀路由怎么设置端口映射规则
- 如何通过浏览器访问家里电脑
- 计算机c语言专业就业方向,计算机专业就业方向
热门文章
- thinkphp项目mysql类关系_ThinkPHP数据库与模型
- 广东轻工计算机多媒体,广东轻工职业技术学院2015年自主招生计算机多媒体技术专业考核大纲...
- JavaScript高级笔记
- JAVA16版本.JDK16即将发布,你准备好了吗?
- 京东数科上市首轮问询「答卷」:与蚂蚁集团有本质区别、信用风险损失有限
- C#三层架构第九课之反射和工厂模式实现多数据库访问
- 记录一个解决了一个下午加一个晚上的问题,关于springMVC上传文件的功能
- 高性能实践IO之Reactor模式
- anaconda3 win7_重装系统win7
- 用JADE创建多agent系统