CodeFirst(反射+特性)

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Reflection;
  5 using System.Text;
  6 using Dapper;
  7 using System.Text.RegularExpressions;
  8 using System.Data.SqlClient;
  9 using System.ComponentModel;
 10 
 11 namespace CodeFirst
 12 {
 13     class Program
 14     {
 15         static readonly string SchemaName;
 16         static readonly string ConnectionString;
 17 
 18         static Program()
 19         {
 20             SchemaName = "22TopWeb";
 21             if (string.IsNullOrWhiteSpace(SchemaName))
 22             {
 23                 throw new Exception("'SchemaName' load failed");
 24             }
 25             if (new[] { "master", "model", "msdb", "tempdb" }.Contains(SchemaName))
 26             {
 27                 throw new Exception("'SchemaName' illegal");
 28             }
 29             ConnectionString = "Data Source=192.168.8.119;User ID=EQCCD_HUNTER;Password=zhey1bu2012;Initial Catalog=master;Pooling=true";
 30             if (string.IsNullOrWhiteSpace(ConnectionString))
 31             {
 32                 throw new Exception("'ConnectionString' load failed");
 33             }
 34             var pattern = @"Initial\s*Catalog\s*=\s*master";
 35             Match match = Regex.Match(ConnectionString, pattern, RegexOptions.IgnoreCase);
 36             if (match.Groups.Count > 0)
 37             {
 38                 //可能需要创建数据库
 39                 CheckSchema(ConnectionString, SchemaName);
 40                 ConnectionString = ConnectionString.Replace(match.Groups[0].Value, "Initial Catalog=" + SchemaName);
 41             }
 42         }
 43 
 44         static void Main(string[] args)
 45         {
 46             var sql = GetTableCreateSql("CodeFirst.TB_Enterprise");
 47 
 48             ExcuteSql(ConnectionString, sql.Replace("GO", "")); //GO只能在查询分析器里使用
 49 
 50             Console.ReadKey();
 51         }
 52 
 53         /// <summary>
 54         /// 
 55         /// </summary>
 56         /// <param name="fullName"></param>
 57         /// <param name="overwrite">如果表已存在,drop后重新创建(true慎用)</param>
 58         /// <returns></returns>
 59         static string GetTableCreateSql(string fullName, bool overwrite = false)
 60         {
 61             var type = Type.GetType(fullName);
 62 
 63             var columnDefinitionList = GetColumnDefinitionList(type);
 64 
 65             //数据库 表名
 66             var tableName = type.Name;
 67             var dbTableNameAttr = type.GetCustomAttributes(false).Where(attr => attr.GetType().Name == "DBTableNameAttribute").SingleOrDefault() as
 68     dynamic;
 69             if (dbTableNameAttr != null)
 70                 tableName = dbTableNameAttr.Name;
 71             //主键列
 72             var primaryKeyArr = (from clmn in columnDefinitionList where clmn.IsPrimaryKey select clmn.ColumnName).ToArray();
 73             //是否 TEXTIMAGE ON
 74             var isTextImageOn = type.GetCustomAttributes(false).Where(attr => attr.GetType().Name == "TextImageOn").Any();
 75 
 76             if (!string.IsNullOrWhiteSpace(tableName) && columnDefinitionList.Count > 0)
 77             {
 78                 var sb = new StringBuilder();
 79 
 80                 sb.AppendFormat(@"USE [{0}]
 81 GO", SchemaName);
 82 
 83                 if (overwrite)
 84                 {
 85                     sb.AppendFormat(@"
 86 
 87 if exists (select 1 from  sysobjects where  id = object_id('{0}') and type = 'U')
 88 drop table {0}
 89 GO", tableName);
 90                 }
 91 
 92                 sb.AppendFormat(@"
 93 
 94 /****** Object:  Table [dbo].[{1}]    Script Date: {2}    Generate By CodeFrist  ******/
 95 SET ANSI_NULLS ON
 96 GO
 97 
 98 SET QUOTED_IDENTIFIER ON
 99 GO
100 
101 SET ANSI_PADDING ON
102 GO
103 
104 CREATE TABLE [dbo].[{1}](", SchemaName, tableName, DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
105 
106                 columnDefinitionList.ForEach(p =>
107                 {
108                     //组合主键 不能定义 IDENTITY
109                     sb.AppendFormat(@"
110     [{0}] [{1}]{2} {3} {4},", p.ColumnName, p.DbType, p.MaxLength > 0 ? "(" + p.MaxLength + ")" : "", p.IsPrimaryKey && primaryKeyArr.Length <= 1 ? "IDENTITY(" + p.Seed + "," + p.Incr + ")" : "", p.IsNullable ? "NULL" : "NOT NULL");
111                 });
112 
113                 if (primaryKeyArr != null && primaryKeyArr.Length > 0)
114                 {
115                     //主键列
116                     sb.AppendFormat(@"
117  CONSTRAINT [PK_{0}] PRIMARY KEY CLUSTERED 
118 (
119     {1}
120 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
121 ", tableName, primaryKeyArr.Aggregate("", (current, cName) => current += string.Format(",[{0}] ASC", cName)).Trim(','));
122                 }
123                 //else //多余的这个逗号可以不去掉
124 
125                 sb.AppendFormat(@"
126 ) ON [PRIMARY] {0}
127 
128 GO
129 
130 SET ANSI_PADDING OFF
131 GO
132 ", isTextImageOn ? "TEXTIMAGE_ON [PRIMARY]" : "");
133 
134                 columnDefinitionList.Where(p => !string.IsNullOrWhiteSpace(p.Description)).ToList().ForEach(p =>
135                 {
136                     //字段说明
137                     sb.AppendFormat(@"
138 EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'{2}' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'{0}', @level2type=N'COLUMN',@level2name=N'{1}'
139 GO
140 ", tableName, p.ColumnName, ToSqlLike(p.Description));
141                 });
142 
143 
144                 return sb.ToString(); //这个格式和Management Studio生成的sql内容一致
145 
146             }
147 
148             return string.Empty;
149         }
150 
151         /// <summary>
152         /// 获取所有列定义(此为重点,反射+特性)
153         /// </summary>
154         /// <param name="type"></param>
155         /// <returns></returns>
156         static List<ColumnDefinition> GetColumnDefinitionList(Type type)
157         {
158             var columnDefinitionList = new List<ColumnDefinition>();
159 
160             var pInfoArr = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
161             foreach (PropertyInfo pInfo in pInfoArr)
162             {
163                 var columnDefinition = new ColumnDefinition() { ColumnName = pInfo.Name };
164 
165                 Console.WriteLine("----------Property Name:{0}-----------", pInfo.Name);
166 
167                 foreach (dynamic attr in pInfo.GetCustomAttributes(false))
168                 {
169                     var attributeName = attr.GetType().Name as string;
170 
171                     var attributeInfoStr = string.Format("Attribute Name:{0}", attributeName);
172                     switch (attributeName)
173                     {
174                         case "PrimaryKeyAttribute":
175                             columnDefinition.IsPrimaryKey = true;
176                             columnDefinition.Seed = attr.Seed;
177                             columnDefinition.Incr = attr.Incr;
178                             columnDefinition.IsPrimaryKey = true;
179                             Console.WriteLine(attributeInfoStr);
180                             break;
181                         case "DataTypeAttribute":
182                             columnDefinition.DbType = attr.DbType;
183                             columnDefinition.MaxLength = attr.MaxLength;
184                             attributeInfoStr += string.Format("(DbType:{0}{1})", columnDefinition.DbType, columnDefinition.MaxLength > 0 ? ",MaxLength:" + columnDefinition.MaxLength : "");
185                             Console.WriteLine(attributeInfoStr);
186                             break;
187                         case "IsNullableAttribute":
188                             columnDefinition.IsNullable = true;
189                             Console.WriteLine(attributeInfoStr);
190                             break;
191                         case "DescriptionAttribute":
192                             columnDefinition.Description = attr.Description; //字段说明
193                             attributeInfoStr += string.Format("(说明:{0})", columnDefinition.Description);
194                             Console.WriteLine(attributeInfoStr);
195                             break;
196                         default:
197                             break;
198                     }
199                 }
200 
201                 if (!string.IsNullOrWhiteSpace(columnDefinition.ColumnName) && !string.IsNullOrWhiteSpace(columnDefinition.DbType))
202                 {
203                     columnDefinitionList.Add(columnDefinition);
204                 }
205 
206                 Console.WriteLine();
207             }
208 
209             return columnDefinitionList;
210         }
211 
212         #region DBHelper
213 
214         /// <summary>
215         /// check数据库是否已存在,不存在则自动创建
216         /// </summary>
217         /// <param name="connectionString"></param>
218         /// <param name="schemaName"></param>
219         static void CheckSchema(string connectionString, string schemaName)
220         {
221             var pattern = @"Initial\s*Catalog\s*=\s*master";
222             Match match = Regex.Match(connectionString, pattern, RegexOptions.IgnoreCase);
223             if (match.Groups.Count == 0)
224             {
225                 throw new ArgumentException();
226             }
227             var sql = string.Format(@"
228 if not exists(select 1 from sysdatabases where name='{0}')
229 create database {0}
230 ", schemaName);
231             ExcuteSql(connectionString, sql);
232         }
233 
234         static bool ExcuteSql(string connectionString, string sql)
235         {
236             try
237             {
238                 using (var conn = new SqlConnection(connectionString))
239                 {
240                     conn.Execute(sql);
241                 }
242                 return true;
243             }
244             catch (Exception ex)
245             {
246                 return false;
247             }
248         }
249 
250         /// <summary>
251         /// 对字符串进行sql格式化,并且符合like查询的格式。 
252         /// </summary>
253         /// <param name="sqlstr"></param>
254         /// <returns></returns>
255         static string ToSqlLike(string sqlstr)
256         {
257             if (string.IsNullOrEmpty(sqlstr)) return string.Empty;
258             StringBuilder str = new StringBuilder(sqlstr);
259             str.Replace("'", "''");
260             str.Replace("[", "[[]");
261             str.Replace("%", "[%]");
262             str.Replace("_", "[_]");
263             return str.ToString();
264         }
265 
266         #endregion
267 
268     }
269 
270     /// <summary>
271     /// 数据库 列定义
272     /// </summary>
273     public class ColumnDefinition
274     {
275         public string ColumnName { get; set; }
276         public bool IsPrimaryKey { get; set; }
277         /// <summary>
278         /// 标示种子
279         /// </summary>
280         public int Seed { get; set; }
281         /// <summary>
282         /// 标示增量
283         /// </summary>
284         public int Incr { get; set; }
285         public string DbType { get; set; }
286         public int MaxLength { get; set; }
287         /// <summary>
288         /// true 可为空, 否则 false 不可为空
289         /// </summary>
290         public bool IsNullable { get; set; }
291         public string Description { get; set; }
292     }
293 
294     #region Custom Attributes
295 
296     [AttributeUsage(AttributeTargets.Class)]
297     /// <summary>
298     /// 数据库 表名
299     /// </summary>
300     public class DBTableNameAttribute : Attribute
301     {
302         public string Name { get; set; }
303     }
304 
305     [AttributeUsage(AttributeTargets.Class)]
306     /// <summary>
307     /// 表的TEXTIMAGE ON特性
308     /// </summary>
309     public class TextImageOnAttribute : Attribute
310     {
311 
312     }
313 
314     [AttributeUsage(AttributeTargets.Property)]
315     /// <summary>
316     /// 主键
317     /// </summary>
318     public class PrimaryKeyAttribute : Attribute
319     {
320         /// <summary>
321         /// 标示种子
322         /// </summary>
323         public int Seed { get; set; }
324         /// <summary>
325         /// 标示增量
326         /// </summary>
327         public int Incr { get; set; }
328     }
329 
330     [AttributeUsage(AttributeTargets.Property)]
331     /// <summary>
332     /// 数据类型
333     /// </summary>
334     public class DataTypeAttribute : Attribute
335     {
336         public string DbType { get; set; }
337         public int MaxLength { get; set; }
338     }
339 
340     [AttributeUsage(AttributeTargets.Property)]
341     /// <summary>
342     /// 允许Null值
343     /// </summary>
344     public class IsNullableAttribute : Attribute
345     {
346 
347     }
348 
349     #endregion
350 
351     #region Table Model
352 
353     [TextImageOn]
354     /// <summary>
355     /// 
356     /// </summary>
357     public class TB_Enterprise
358     {
359         [PrimaryKey(Seed = 1, Incr = 1)]
360         [DataType(DbType = "int")]
361         public int EnterpriseId { get; set; }
362 
363         [DataType(DbType = "int")]
364         public int Status { get; set; }
365 
366         [DataType(DbType = "int")]
367         [IsNullable]
368         public int? IsFamous { get; set; }
369 
370         [DataType(DbType = "int")]
371         [IsNullable]
372         public int? CustomerLevel { get; set; }
373 
374         [IsNullable]
375         [DataType(DbType = "nvarchar", MaxLength = 256)]
376         [Description("企业名称")]
377         /// <summary>
378         /// 企业名称
379         /// </summary>
380         public string Name { get; set; }
381 
382         [IsNullable]
383         [DataType(DbType = "nvarchar", MaxLength = 300)]
384         public string Industry { get; set; }
385 
386         [DataType(DbType = "int")]
387         [IsNullable]
388         public int? Mode { get; set; }
389 
390         [DataType(DbType = "int")]
391         [IsNullable]
392         public int? Scale { get; set; }
393 
394         [DataType(DbType = "nvarchar", MaxLength = 256)]
395         [IsNullable]
396         public string City { get; set; }
397 
398         [DataType(DbType = "nvarchar", MaxLength = 512)]
399         [IsNullable]
400         public string WebSite { get; set; }
401 
402         [DataType(DbType = "ntext")]
403         [IsNullable]
404         public string DescText { get; set; }
405 
406         [DataType(DbType = "datetime")]
407         public DateTime CreateDate { get; set; }
408 
409         [DataType(DbType = "datetime")]
410         public DateTime ModifyDate { get; set; }
411 
412         [DataType(DbType = "datetime")]
413         [IsNullable]
414         public DateTime? ApproveDate { get; set; }
415 
416         [DataType(DbType = "nvarchar", MaxLength = 50)]
417         [IsNullable]
418         public string SourceName { get; set; }
419 
420         [DataType(DbType = "nvarchar", MaxLength = 256)]
421         [IsNullable]
422         public string License { get; set; }
423 
424         [DataType(DbType = "varchar", MaxLength = 20)]
425         [IsNullable]
426         public string CreateUser { get; set; }
427 
428         [DataType(DbType = "varchar", MaxLength = 20)]
429         [IsNullable]
430         public string ModifyUser { get; set; }
431 
432         [DataType(DbType = "int")]
433         [IsNullable]
434         public int? ProcessStatus { get; set; }
435 
436         [DataType(DbType = "varchar", MaxLength = 50)]
437         [IsNullable]
438         public string Abbr { get; set; }
439 
440         [DataType(DbType = "varchar", MaxLength = 1)]
441         [IsNullable]
442         public string NameInitial { get; set; }
443 
444         [DataType(DbType = "float")]
445         [IsNullable]
446         public decimal? Activity { get; set; }
447 
448         [DataType(DbType = "nvarchar", MaxLength = 200)]
449         [IsNullable]
450         public string Tags { get; set; }
451 
452         [DataType(DbType = "nvarchar", MaxLength = 50)]
453         [IsNullable]
454         public string ConsultantName { get; set; }
455 
456         [DataType(DbType = "nvarchar", MaxLength = 500)]
457         [IsNullable]
458         public string ConsultantComment { get; set; }
459 
460         [DataType(DbType = "int")]
461         [IsNullable]
462         public int? ConsultantId { get; set; }
463 
464         [DataType(DbType = "int")]
465         [IsNullable]
466         public int? DecoratePercent { get; set; }
467 
468         [DataType(DbType = "nvarchar", MaxLength = 100)]
469         [IsNullable]
470         public string ShortDesc { get; set; }
471 
472         [DataType(DbType = "int")]
473         [IsNullable]
474         public int? CertificationStatus { get; set; }
475 
476         [DataType(DbType = "bit")]
477         [IsNullable]
478         public bool? IsBDRecommended { get; set; }
479 
480         [DataType(DbType = "int")]
481         [IsNullable]
482         public int? ApproveStatus { get; set; }
483 
484         [DataType(DbType = "varchar", MaxLength = 500)]
485         [IsNullable]
486         public string ApproveResult { get; set; }
487 
488         [DataType(DbType = "int")]
489         [IsNullable]
490         public int? ApproveByUserId { get; set; }
491     }
492 
493     #endregion
494 
495 }

 

posted @ 2016-03-03 13:57  Frozen.Zhang  阅读(792)  评论(1编辑  收藏  举报