Topshelf+Quartz.net+Dapper+Npoi(二)
quartznet
上篇说到quartznet这个东东,topshelf+quartznet有很多不错的文章,可以查看七七同学的文章(http://www.cnblogs.com/jys509/p/4628926.html)。这里我主要说说cron表达式,如果玩过linux下定时任务的肯定不陌生。
官方英文介绍地址:http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/crontrigger.html
cron expressions 整体上还是非常容易理解的,只有一点需要注意:"?"号的用法,看下文可以知道“?”可以用在 day of month 和 day of week中,他主要是为了解决如下场景,如:每月的1号的每小时的31分钟,正确的表达式是:* 31 * 1 * ?,而不能是:* 31 * 1 * *,因为这样代表每周的任意一天。
由7段构成:秒 分 时 日 月 星期 年(可选)
"-" :表示范围 MON-WED表示星期一到星期三
"," :表示列举 MON,WEB表示星期一和星期三
"*" :表是“每”,每月,每天,每周,每年等
"/" :表示增量:0/15(处于分钟段里面) 每15分钟,在0分以后开始,3/20 每20分钟,从3分钟以后开始
"?" :只能出现在日,星期段里面,表示不指定具体的值
"L" :只能出现在日,星期段里面,是Last的缩写,一个月的最后一天,一个星期的最后一天(星期六)
"W" :表示工作日,距离给定值最近的工作日
"#" :表示一个月的第几个星期几,例如:"6#3"表示每个月的第三个星期五(1=SUN...6=FRI,7=SAT)
官方实例
Expression | Meaning |
---|---|
0 0 12 * * ? | 每天中午12点触发 |
0 15 10 ? * * | 每天上午10:15触发 |
0 15 10 * * ? | 每天上午10:15触发 |
0 15 10 * * ? * | 每天上午10:15触发 |
0 15 10 * * ? 2005 | 2005年的每天上午10:15触发 |
0 * 14 * * ? | 在每天下午2点到下午2:59期间的每1分钟触发 |
0 0/5 14 * * ? | 在每天下午2点到下午2:55期间的每5分钟触发 |
0 0/5 14,18 * * ? | 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 |
0 0-5 14 * * ? | 在每天下午2点到下午2:05期间的每1分钟触发 |
0 10,44 14 ? 3 WED | 每年三月的星期三的下午2:10和2:44触发 |
0 15 10 ? * MON-FRI | 周一至周五的上午10:15触发 |
0 15 10 15 * ? | 每月15日上午10:15触发 |
0 15 10 L * ? | 每月最后一日的上午10:15触发 |
0 15 10 L-2 * ? | Fire at 10:15am on the 2nd-to-last last day of every month |
0 15 10 ? * 6L | 每月的最后一个星期五上午10:15触发 |
0 15 10 ? * 6L | Fire at 10:15am on the last Friday of every month |
0 15 10 ? * 6L 2002-2005 | 2002年至2005年的每月的最后一个星期五上午10:15触发 |
0 15 10 ? * 6#3 | 每月的第三个星期五上午10:15触发 |
0 0 12 1/5 * ? | Fire at 12pm (noon) every 5 days every month, starting on the first day of the month. |
0 11 11 11 11 ? | Fire every November 11th at 11:11am. |
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "log4net.config")); 6 HostFactory.Run(x => 7 { 8 x.UseLog4Net(); 9 x.Service<ServiceRunner>(); 10 x.RunAsLocalSystem(); 11 12 x.SetDescription("Windows服务导出数据"); 13 x.SetDisplayName("QuartzTopShelf"); 14 x.SetServiceName("QuartzTopShelfService"); 15 x.EnablePauseAndContinue(); 16 17 }); 18 } 19 }
1 public class ServiceRunner : ServiceControl, ServiceSuspend 2 { 3 private readonly IScheduler scheduler; 4 5 public ServiceRunner() 6 { 7 scheduler = StdSchedulerFactory.GetDefaultScheduler(); 8 } 9 10 public bool Start(HostControl hostControl) 11 { 12 scheduler.Start(); 13 return true; 14 } 15 16 public bool Stop(HostControl hostControl) 17 { 18 scheduler.Shutdown(false); 19 return true; 20 } 21 22 public bool Continue(HostControl hostControl) 23 { 24 scheduler.ResumeAll(); 25 return true; 26 } 27 28 public bool Pause(HostControl hostControl) 29 { 30 scheduler.PauseAll(); 31 return true; 32 } 33 34 }
Dapper
Dapper是一款轻量级ORM工具(Github)。如果你在小的项目中,使用Entity Framework、NHibernate 来处理大数据访问及关系映射,未免有点杀鸡用牛刀。你又觉得ORM省时省力,这时Dapper 将是你不二的选择。
Dapper优势:
- 轻量。只有一个文件(SqlMapper.cs),编译完成之后只有120k(好象是变胖了)
- 速度快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
- 支持多种数据库。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
- 可以映射一对一,一对多,多对多等多种关系。
- 性能高。通过Emit反射IDataReader的序列队列,来快速的得到和产生对象,性能不错。
- 支持FrameWork2.0,3.0,3.5,4.0,4.5
上篇已经说过我用dapper的原因,就是为了方便而已。(使用dapper可以不去考虑你的数据库是sqlserver还是mysql,上层只需要配置一下连接串就行,方便的很)
直接上代码(用的是仓储模式):
IRepository.cs
1 public interface IRepository<TEntity> where TEntity : class 2 { 3 object Insert(TEntity entity); 4 5 void Insert(IList<TEntity> list); 6 7 bool Update(TEntity entity); 8 9 bool Delete(TEntity entity); 10 11 TEntity GetEntity(int id); 12 13 int GetCount(object predicate); 14 15 /// <summary> 16 /// 分页获取数据 17 /// </summary> 18 /// <param name="predicate"></param> 19 /// <param name="page">页数</param> 20 /// <param name="resultsPerPage">每页数量</param> 21 /// <param name="sort">排序</param> 22 /// <returns></returns> 23 IList<TEntity> GetPageList(object predicate, int pageIndex, int pageSize, IList<ISort> sort); 24 25 }
Repository.cs
1 public class Repository<TEntity> : IRepository<TEntity> where TEntity : class 2 { 3 private string _connName = null; 4 /// <summary> 5 /// 数据库连接名称 6 /// </summary> 7 public string connName { set { _connName = value; } } 8 9 public object Insert(TEntity entity) 10 { 11 using (var db = DbFactory.GetDatabase(_connName)) 12 { 13 14 return db.Insert(entity); 15 } 16 } 17 18 public void Insert(IList<TEntity> list) 19 { 20 using (var db = DbFactory.GetDatabase(_connName)) 21 { 22 db.Insert<TEntity>(list); 23 } 24 } 25 26 public bool Update(TEntity entity) 27 { 28 using (var db = DbFactory.GetDatabase(_connName)) 29 { 30 return db.Update(entity); 31 } 32 } 33 34 public bool Delete(TEntity entity) 35 { 36 using (var db = DbFactory.GetDatabase(_connName)) 37 { 38 return db.Delete(entity); 39 } 40 } 41 42 public IList<TEntity> GetList() 43 { 44 using (var db = DbFactory.GetDatabase(_connName)) 45 { 46 return db.GetList<TEntity>().ToList(); 47 } 48 } 49 public IList<TEntity> GetList(object predicate, IList<ISort> sort = null) 50 { 51 using (var db = DbFactory.GetDatabase(_connName)) 52 { 53 return db.GetList<TEntity>(predicate, sort).ToList(); 54 } 55 56 } 57 public IList<TEntity> GetPageList(object predicate, int pageIndex, int pageSize, IList<ISort> sort) 58 { 59 using (var db = DbFactory.GetDatabase(_connName)) 60 { 61 return db.GetPage<TEntity>(predicate, sort, pageIndex, pageSize).ToList(); 62 } 63 } 64 65 public int GetCount(object predicate) 66 { 67 using (var db = DbFactory.GetDatabase(_connName)) 68 { 69 return db.Count<TEntity>(predicate); 70 } 71 } 72 73 public TEntity GetEntity(int id) 74 { 75 using (var db = DbFactory.GetDatabase(_connName)) 76 { 77 return db.Get<TEntity>(id); 78 } 79 } 80 public TEntity GetEntity(string id) 81 { 82 using (var db = DbFactory.GetDatabase(_connName)) 83 { 84 return db.Get<TEntity>(id); 85 } 86 } 87 }
DbFactory.CS
1 public class DbFactory 2 { 3 /// 得到web.config里配置项的数据库连接字符串。 4 private static readonly ConnectionStringSettings _settings = ConfigurationManager.ConnectionStrings["XX"]; 5 6 public static IDbConnection GetDbConnection(string connName = null) 7 { 8 ConnectionStringSettings settings = _settings; 9 if (connName != null) 10 settings = ConfigurationManager.ConnectionStrings[connName]; 11 if (settings == null) 12 throw new Exception("数据库连接字符串不能为空!"); 13 DbServerType type = (DbServerType)Enum.Parse(typeof(DbServerType), settings.ProviderName); 14 return GetDbConnection(settings.ConnectionString, type); 15 } 16 17 public static IDbConnection GetDbConnection(string connStr, DbServerType type) 18 { 19 if (string.IsNullOrEmpty(connStr)) throw new Exception("数据库连接字符串不能为空!"); 20 21 IDbConnection conn = null; 22 switch (type) 23 { 24 case DbServerType.MsSqlServer: 25 conn = new SqlConnection(connStr); 26 break; 27 case DbServerType.MySQL: 28 conn = new MySqlConnection(connStr); 29 break; 30 case DbServerType.SQLite: 31 case DbServerType.Orcale: 32 case DbServerType.DB2: 33 case DbServerType.MongoDB: 34 default: 35 throw new NotImplementedException("尚未实现对该数据库的支持!"); 36 } 37 conn.Open(); 38 return conn; 39 } 40 41 public static IDatabase GetDatabase(string connName = null) 42 { 43 ConnectionStringSettings settings = _settings; 44 if (connName != null) 45 settings = ConfigurationManager.ConnectionStrings[connName]; 46 if (settings == null) 47 throw new Exception("数据库连接字符串不能为空!"); 48 DbServerType type = (DbServerType)Enum.Parse(typeof(DbServerType), settings.ProviderName); 49 return GetDatabase(settings.ConnectionString, type); 50 } 51 52 public static IDatabase GetDatabase(string connStr, DbServerType type) 53 { 54 if (string.IsNullOrEmpty(connStr)) throw new Exception("数据库连接字符串不能为空!"); 55 56 IDbConnection conn = null; 57 IDapperExtensionsConfiguration config = null; 58 ISqlGenerator sqlGenerator = null; 59 60 switch (type) 61 { 62 case DbServerType.MsSqlServer: 63 conn = new SqlConnection(connStr); 64 config = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new SqlServerDialect()); 65 sqlGenerator = new SqlGeneratorImpl(config); 66 break; 67 case DbServerType.MySQL: 68 conn = new MySqlConnection(connStr); 69 config = new DapperExtensionsConfiguration(typeof(AutoClassMapper<>), new List<Assembly>(), new MySqlDialect()); 70 sqlGenerator = new SqlGeneratorImpl(config); 71 break; 72 case DbServerType.SQLite: 73 case DbServerType.Orcale: 74 case DbServerType.DB2: 75 case DbServerType.MongoDB: 76 default: 77 throw new NotImplementedException("尚未实现对该数据库的支持!"); 78 } 79 return new Database(conn, sqlGenerator); 80 } 81 }
NPOI
npoi没什么好说的,直接nuget上下载dll,就可以使用了,有兴趣的可以下载源码看看,用它做一些excel的样式也是很方便的。
1 public static class NPOIHelper 2 { 3 public static void ExportToFile(DataSet dataSet, string fileFullPath) 4 { 5 List<DataTable> dts = new List<DataTable>(); 6 foreach (DataTable dt in dataSet.Tables) dts.Add(dt); 7 ExportToFile(dts, fileFullPath); 8 } 9 public static void ExportToFile(DataTable dataTable, string fileFullPath) 10 { 11 List<DataTable> dts = new List<DataTable>(); 12 dts.Add(dataTable); 13 ExportToFile(dts, fileFullPath); 14 } 15 public static void ExportToFile(IEnumerable<DataTable> dataTables, string fileFullPath) 16 { 17 IWorkbook workbook = new XSSFWorkbook(); 18 int i = 0; 19 foreach (DataTable dt in dataTables) 20 { 21 string sheetName = string.IsNullOrEmpty(dt.TableName) 22 ? "Sheet " + (++i).ToString() 23 : dt.TableName; 24 ISheet sheet = workbook.CreateSheet(sheetName); 25 26 IRow headerRow = sheet.CreateRow(0); 27 for (int j = 0; j < dt.Columns.Count; j++) 28 { 29 string columnName = string.IsNullOrEmpty(dt.Columns[j].ColumnName) 30 ? "Column " + j.ToString() 31 : dt.Columns[j].ColumnName; 32 headerRow.CreateCell(j).SetCellValue(columnName); 33 } 34 35 for (int a = 0; a < dt.Rows.Count; a++) 36 { 37 DataRow dr = dt.Rows[a]; 38 IRow row = sheet.CreateRow(a + 1); 39 for (int b = 0; b < dt.Columns.Count; b++) 40 { 41 row.CreateCell(b).SetCellValue(dr[b] != DBNull.Value ? dr[b].ToString() : string.Empty); 42 } 43 } 44 } 45 46 using (FileStream fs = File.Create(fileFullPath)) 47 { 48 workbook.Write(fs); 49 } 50 } 51 52 public static List<DataTable> GetDataTablesFrom(string xlsxFile) 53 { 54 if (!File.Exists(xlsxFile)) 55 throw new FileNotFoundException("文件不存在"); 56 57 List<DataTable> result = new List<DataTable>(); 58 Stream stream = new MemoryStream(File.ReadAllBytes(xlsxFile)); 59 IWorkbook workbook = new XSSFWorkbook(stream); 60 for (int i = 0; i < workbook.NumberOfSheets; i++) 61 { 62 DataTable dt = new DataTable(); 63 ISheet sheet = workbook.GetSheetAt(i); 64 IRow headerRow = sheet.GetRow(0); 65 66 int cellCount = headerRow.LastCellNum; 67 for (int j = headerRow.FirstCellNum; j < cellCount; j++) 68 { 69 DataColumn column = new DataColumn(headerRow.GetCell(j).StringCellValue); 70 dt.Columns.Add(column); 71 } 72 73 int rowCount = sheet.LastRowNum; 74 for (int a = (sheet.FirstRowNum + 1); a < rowCount; a++) 75 { 76 IRow row = sheet.GetRow(a); 77 if (row == null) continue; 78 79 DataRow dr = dt.NewRow(); 80 for (int b = row.FirstCellNum; b < cellCount; b++) 81 { 82 if (row.GetCell(b) == null) continue; 83 dr[b] = row.GetCell(b).ToString(); 84 } 85 86 dt.Rows.Add(dr); 87 } 88 result.Add(dt); 89 } 90 stream.Close(); 91 92 return result; 93 } 94 }
好了,就说到这里吧,欢迎拍砖。