记一次使用Dapper 进行的数据迁移和清洗工作

 背景介绍:

  国内一流的财经门户站点做栏目调整,需要调整相应的数据调整。

目前站点数据库采用的是 id主键自增长,根据具体业务,将数据存在多张表。

相同业务的,数据存在一张表。每一条新闻资讯都有相应的新闻类型id 和新闻id。通过 http:// www.xx.com/{type}-{newsid}.html 方式,去读取相关的新闻资讯,其中type 表示新闻类别,newsid表示新闻id。每个资讯频道有多个子栏目,类似于和讯网,

新闻频道包含了 滚动、国内、国际等资讯,在新闻表中,使用type 类别进行区分。

同一频道下或者多个频道下 的数据存放在一张表。

不同频道或者耦合性比较低的存放在不同的表中, 类似于 新闻是张新闻表,股票是张股票表。

运营团队提出,在新的形势下,需要对整站的栏目进行调整,同时要对搜索引擎收录的资讯做301重定向,在数据清理过程中,需要提供重定向依据。

 

任务拆解和具体实现: 

  整体需求大致分类:
    1、同一张数据表之间的调整,仅仅调整资讯type ,需要生成 重定向依据
  类似于以前的地址 http://news.xx.com/111,1101.html 重定向到 http:// news.xx.com/113,1101.html
    2、不同数据表之间的数据合并,因为主键使用int 自增长,所以避免不了id重复,需要提供重定向依据,类似于
  http://news.xx.com/111,1101.html 重定向到 http://stock.xx.com/222,2202.html

根据以上需求,决定使用 C# 控制台直接跑数据,然后将重定向的 数据存入指定的数据表中。
在数据库连接的选择上,有3中,

  •  linq to sql;
  • SqlHpler 帮助类;
  • Dapper

  最终选择了 Dapper,原因是据说速度比Ado.net 快。2、接触下这个轻型的 Orm。

  新建控制台应用程序

  添加Dapper 引用。通过 nuget 安装Dapper, 依次打开 工具->Nuget包管理器->程序包管理器控制台,在 程序包管理器控制台 输入Install-Package Dapper 后,敲回车,静等安装成功提示。

  完成安装后,创建Dapper帮助类 DapperHelper,在App.config中配置数据库连接字符串。代码如下: 

 1 public class DapperHelper
 2     {
 3         private static string mssqlConn = ConfigurationManager.ConnectionStrings["appConn"].ToString().Trim();
 4 
 5         /// <summary>
 6         /// Dapper 帮助类
 7         /// </summary>
 8         /// <returns></returns>
 9         public static DbConnection MssqlConnection()
10         {
11             SqlConnection conn = new SqlConnection(mssqlConn);  
12             conn.Open();  // 打开连接
13 
14             return conn;
15         }
16 }
Dapper帮助类

  测试数据库连接情况

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             // 测试 数据库连接情况
 6             using (DbConnection conn = DapperHelper.MssqlConnection())
 7             {
 8                 dynamic time = conn.QueryFirstOrDefault("select getdate();");
 9             }
10         }
11     }
测试数据库连接情况

  此时已经可以联通数据库了。

  因为是做数据的合并和迁移的,需要做相关的日志记录和打印当前情况,做了简单的日志处理帮助类,

  为什么不用log4net 或者其他的呢?
  因为本身就比较简单,所以就造了个轮子,核心代码如下:

 1 /// <summary>
 2     ///  简单日志帮助类
 3     /// </summary>
 4     public class LogHelper
 5     {
 6 
 7         private static object loker = new object();
 8 
 9         /// <summary>
10         ///  添加日志
11         /// </summary>
12         /// <param name="log"></param>
13         public static void Write(string log)
14         {
15             log = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\r\n" + log;
16 
17             WriteTextLog(log);   //记录日志到文本文件
18             Console.WriteLine(log);  //打印日志到控制台
19         }
20 
21         /// <summary>
22         /// 写日志到文本文件
23         /// </summary>
24         /// <param name="log"></param>
25         private static void WriteTextLog(string log)
26         {
27             lock (loker)  // 为什么要用 lock?主要是因为 如果并发的话,会有异常的
28             {
29                 string path = AppDomain.CurrentDomain.BaseDirectory + @"Log\";
30                 if (!Directory.Exists(path))
31                     Directory.CreateDirectory(path);
32 
33                 string fileFullPath = path + DateTime.Now.ToString("yyyy-MM-dd") + ".System.txt";
34                  
35                 StreamWriter sw;
36                 if (!File.Exists(fileFullPath))
37                 {
38                     sw = File.CreateText(fileFullPath);
39                 }
40                 else
41                 {
42                     sw = File.AppendText(fileFullPath);
43                 }
44                 sw.WriteLine(log);
45                 sw.Close();
46             }
47 
48         }
49     }
简单的日志帮助类

  调用 方式 LogHelper.Write("清洗程序已经启动");
  会自动打印到控制台和 记录日志。

  主要涉及到的功能点:

    资讯表主键为ID自增张,有些不同表之间的ID有重复,怎么处理相关的ID?

  我这边的思路,先将数据按照分页大小取出来,每次清洗5000条记录,取出本表最大值,然后再去设置表的 标识值

  代码:

1                 dynamic _maxId = conn.QueryFirst("select max(id) as maxId from CLOUD_NEWS_GLOBAL ");
2                 int maxId = int.Parse(_maxId.maxId.ToString());
3                 maxId = maxId + 1000;  
4                 conn.Execute("DBCC CHECKIDENT(CLOUD_NEWS_GLOBAL,RESEED," + maxId + ")");
5     
设置标识值

  因为资讯的主键值会做改变,所以插入代码主要是用的以下Sql。

1                         conn.Execute(
2                         @"SET IDENTITY_INSERT CLOUD_NEWS_GLOBAL ON 
3                         INSERT INTO CLOUD_NEWS_GLOBAL([ID],[INDUSTRYID],...)         
4                         values(@ID ,@INDUSTRYID ....)
5                         SET IDENTITY_INSERT CLOUD_NEWS_GLOBAL OFF",
6                        info);
7     
插入数据代码

  主要是设置允许 主键显示插入值。

  总结:

        为什么没有采用异步的方式开几个线程一起搞?主要是我的观点是,保证数据平稳的迁移合并,比速度要重要。宁愿画点时间盯着控制

  台程序输出日志

转载于:https://www.cnblogs.com/nysoft/p/6744027.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值