CodeFirst(反射+特性)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Dapper;
using System.Text.RegularExpressions;
using System.Data.SqlClient;
using System.ComponentModel; namespace CodeFirst
{
class Program
{
static readonly string SchemaName;
static readonly string ConnectionString; static Program()
{
SchemaName = "22TopWeb";
if (string.IsNullOrWhiteSpace(SchemaName))
{
throw new Exception("'SchemaName' load failed");
}
if (new[] { "master", "model", "msdb", "tempdb" }.Contains(SchemaName))
{
throw new Exception("'SchemaName' illegal");
}
ConnectionString = "Data Source=192.168.8.119;User ID=EQCCD_HUNTER;Password=zhey1bu2012;Initial Catalog=master;Pooling=true";
if (string.IsNullOrWhiteSpace(ConnectionString))
{
throw new Exception("'ConnectionString' load failed");
}
var pattern = @"Initial\s*Catalog\s*=\s*master";
Match match = Regex.Match(ConnectionString, pattern, RegexOptions.IgnoreCase);
if (match.Groups.Count > )
{
//可能需要创建数据库
CheckSchema(ConnectionString, SchemaName);
ConnectionString = ConnectionString.Replace(match.Groups[].Value, "Initial Catalog=" + SchemaName);
}
} static void Main(string[] args)
{
var sql = GetTableCreateSql("CodeFirst.TB_Enterprise"); ExcuteSql(ConnectionString, sql.Replace("GO", "")); //GO只能在查询分析器里使用 Console.ReadKey();
} /// <summary>
///
/// </summary>
/// <param name="fullName"></param>
/// <param name="overwrite">如果表已存在,drop后重新创建(true慎用)</param>
/// <returns></returns>
static string GetTableCreateSql(string fullName, bool overwrite = false)
{
var type = Type.GetType(fullName); var columnDefinitionList = GetColumnDefinitionList(type); //数据库 表名
var tableName = type.Name;
var dbTableNameAttr = type.GetCustomAttributes(false).Where(attr => attr.GetType().Name == "DBTableNameAttribute").SingleOrDefault() as
dynamic;
if (dbTableNameAttr != null)
tableName = dbTableNameAttr.Name;
//主键列
var primaryKeyArr = (from clmn in columnDefinitionList where clmn.IsPrimaryKey select clmn.ColumnName).ToArray();
//是否 TEXTIMAGE ON
var isTextImageOn = type.GetCustomAttributes(false).Where(attr => attr.GetType().Name == "TextImageOn").Any(); if (!string.IsNullOrWhiteSpace(tableName) && columnDefinitionList.Count > )
{
var sb = new StringBuilder(); sb.AppendFormat(@"USE [{0}]
GO", SchemaName); if (overwrite)
{
sb.AppendFormat(@" if exists (select 1 from sysobjects where id = object_id('{0}') and type = 'U')
drop table {0}
GO", tableName);
} sb.AppendFormat(@" /****** Object: Table [dbo].[{1}] Script Date: {2} Generate By CodeFrist ******/
SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO SET ANSI_PADDING ON
GO CREATE TABLE [dbo].[{1}](", SchemaName, tableName, DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")); columnDefinitionList.ForEach(p =>
{
//组合主键 不能定义 IDENTITY
sb.AppendFormat(@"
[{0}] [{1}]{2} {3} {4},", p.ColumnName, p.DbType, p.MaxLength > ? "(" + p.MaxLength + ")" : "", p.IsPrimaryKey && primaryKeyArr.Length <= ? "IDENTITY(" + p.Seed + "," + p.Incr + ")" : "", p.IsNullable ? "NULL" : "NOT NULL");
}); if (primaryKeyArr != null && primaryKeyArr.Length > )
{
//主键列
sb.AppendFormat(@"
CONSTRAINT [PK_{0}] PRIMARY KEY CLUSTERED
(
{1}
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
", tableName, primaryKeyArr.Aggregate("", (current, cName) => current += string.Format(",[{0}] ASC", cName)).Trim(','));
}
//else //多余的这个逗号可以不去掉 sb.AppendFormat(@"
) ON [PRIMARY] {0} GO SET ANSI_PADDING OFF
GO
", isTextImageOn ? "TEXTIMAGE_ON [PRIMARY]" : ""); columnDefinitionList.Where(p => !string.IsNullOrWhiteSpace(p.Description)).ToList().ForEach(p =>
{
//字段说明
sb.AppendFormat(@"
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}'
GO
", tableName, p.ColumnName, ToSqlLike(p.Description));
}); return sb.ToString(); //这个格式和Management Studio生成的sql内容一致 } return string.Empty;
} /// <summary>
/// 获取所有列定义(此为重点,反射+特性)
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
static List<ColumnDefinition> GetColumnDefinitionList(Type type)
{
var columnDefinitionList = new List<ColumnDefinition>(); var pInfoArr = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (PropertyInfo pInfo in pInfoArr)
{
var columnDefinition = new ColumnDefinition() { ColumnName = pInfo.Name }; Console.WriteLine("----------Property Name:{0}-----------", pInfo.Name); foreach (dynamic attr in pInfo.GetCustomAttributes(false))
{
var attributeName = attr.GetType().Name as string; var attributeInfoStr = string.Format("Attribute Name:{0}", attributeName);
switch (attributeName)
{
case "PrimaryKeyAttribute":
columnDefinition.IsPrimaryKey = true;
columnDefinition.Seed = attr.Seed;
columnDefinition.Incr = attr.Incr;
columnDefinition.IsPrimaryKey = true;
Console.WriteLine(attributeInfoStr);
break;
case "DataTypeAttribute":
columnDefinition.DbType = attr.DbType;
columnDefinition.MaxLength = attr.MaxLength;
attributeInfoStr += string.Format("(DbType:{0}{1})", columnDefinition.DbType, columnDefinition.MaxLength > ? ",MaxLength:" + columnDefinition.MaxLength : "");
Console.WriteLine(attributeInfoStr);
break;
case "IsNullableAttribute":
columnDefinition.IsNullable = true;
Console.WriteLine(attributeInfoStr);
break;
case "DescriptionAttribute":
columnDefinition.Description = attr.Description; //字段说明
attributeInfoStr += string.Format("(说明:{0})", columnDefinition.Description);
Console.WriteLine(attributeInfoStr);
break;
default:
break;
}
} if (!string.IsNullOrWhiteSpace(columnDefinition.ColumnName) && !string.IsNullOrWhiteSpace(columnDefinition.DbType))
{
columnDefinitionList.Add(columnDefinition);
} Console.WriteLine();
} return columnDefinitionList;
} #region DBHelper /// <summary>
/// check数据库是否已存在,不存在则自动创建
/// </summary>
/// <param name="connectionString"></param>
/// <param name="schemaName"></param>
static void CheckSchema(string connectionString, string schemaName)
{
var pattern = @"Initial\s*Catalog\s*=\s*master";
Match match = Regex.Match(connectionString, pattern, RegexOptions.IgnoreCase);
if (match.Groups.Count == )
{
throw new ArgumentException();
}
var sql = string.Format(@"
if not exists(select 1 from sysdatabases where name='{0}')
create database {0}
", schemaName);
ExcuteSql(connectionString, sql);
} static bool ExcuteSql(string connectionString, string sql)
{
try
{
using (var conn = new SqlConnection(connectionString))
{
conn.Execute(sql);
}
return true;
}
catch (Exception ex)
{
return false;
}
} /// <summary>
/// 对字符串进行sql格式化,并且符合like查询的格式。
/// </summary>
/// <param name="sqlstr"></param>
/// <returns></returns>
static string ToSqlLike(string sqlstr)
{
if (string.IsNullOrEmpty(sqlstr)) return string.Empty;
StringBuilder str = new StringBuilder(sqlstr);
str.Replace("'", "''");
str.Replace("[", "[[]");
str.Replace("%", "[%]");
str.Replace("_", "[_]");
return str.ToString();
} #endregion } /// <summary>
/// 数据库 列定义
/// </summary>
public class ColumnDefinition
{
public string ColumnName { get; set; }
public bool IsPrimaryKey { get; set; }
/// <summary>
/// 标示种子
/// </summary>
public int Seed { get; set; }
/// <summary>
/// 标示增量
/// </summary>
public int Incr { get; set; }
public string DbType { get; set; }
public int MaxLength { get; set; }
/// <summary>
/// true 可为空, 否则 false 不可为空
/// </summary>
public bool IsNullable { get; set; }
public string Description { get; set; }
} #region Custom Attributes [AttributeUsage(AttributeTargets.Class)]
/// <summary>
/// 数据库 表名
/// </summary>
public class DBTableNameAttribute : Attribute
{
public string Name { get; set; }
} [AttributeUsage(AttributeTargets.Class)]
/// <summary>
/// 表的TEXTIMAGE ON特性
/// </summary>
public class TextImageOnAttribute : Attribute
{ } [AttributeUsage(AttributeTargets.Property)]
/// <summary>
/// 主键
/// </summary>
public class PrimaryKeyAttribute : Attribute
{
/// <summary>
/// 标示种子
/// </summary>
public int Seed { get; set; }
/// <summary>
/// 标示增量
/// </summary>
public int Incr { get; set; }
} [AttributeUsage(AttributeTargets.Property)]
/// <summary>
/// 数据类型
/// </summary>
public class DataTypeAttribute : Attribute
{
public string DbType { get; set; }
public int MaxLength { get; set; }
} [AttributeUsage(AttributeTargets.Property)]
/// <summary>
/// 允许Null值
/// </summary>
public class IsNullableAttribute : Attribute
{ } #endregion #region Table Model [TextImageOn]
/// <summary>
///
/// </summary>
public class TB_Enterprise
{
[PrimaryKey(Seed = , Incr = )]
[DataType(DbType = "int")]
public int EnterpriseId { get; set; } [DataType(DbType = "int")]
public int Status { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? IsFamous { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? CustomerLevel { get; set; } [IsNullable]
[DataType(DbType = "nvarchar", MaxLength = )]
[Description("企业名称")]
/// <summary>
/// 企业名称
/// </summary>
public string Name { get; set; } [IsNullable]
[DataType(DbType = "nvarchar", MaxLength = )]
public string Industry { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? Mode { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? Scale { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string City { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string WebSite { get; set; } [DataType(DbType = "ntext")]
[IsNullable]
public string DescText { get; set; } [DataType(DbType = "datetime")]
public DateTime CreateDate { get; set; } [DataType(DbType = "datetime")]
public DateTime ModifyDate { get; set; } [DataType(DbType = "datetime")]
[IsNullable]
public DateTime? ApproveDate { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string SourceName { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string License { get; set; } [DataType(DbType = "varchar", MaxLength = )]
[IsNullable]
public string CreateUser { get; set; } [DataType(DbType = "varchar", MaxLength = )]
[IsNullable]
public string ModifyUser { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? ProcessStatus { get; set; } [DataType(DbType = "varchar", MaxLength = )]
[IsNullable]
public string Abbr { get; set; } [DataType(DbType = "varchar", MaxLength = )]
[IsNullable]
public string NameInitial { get; set; } [DataType(DbType = "float")]
[IsNullable]
public decimal? Activity { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string Tags { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string ConsultantName { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string ConsultantComment { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? ConsultantId { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? DecoratePercent { get; set; } [DataType(DbType = "nvarchar", MaxLength = )]
[IsNullable]
public string ShortDesc { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? CertificationStatus { get; set; } [DataType(DbType = "bit")]
[IsNullable]
public bool? IsBDRecommended { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? ApproveStatus { get; set; } [DataType(DbType = "varchar", MaxLength = )]
[IsNullable]
public string ApproveResult { get; set; } [DataType(DbType = "int")]
[IsNullable]
public int? ApproveByUserId { get; set; }
} #endregion }
CodeFirst(反射+特性)的更多相关文章
- FreeSql (三十五)CodeFirst 自定义特性
比如项目内已经使用了其它 orm,如 efcore,这样意味着实体中可能存在 [Key],但它与 FreeSql [Column(IsPrimary = true] 不同. Q: FreeSql 实体 ...
- C#利用反射+特性实现简单的实体映射数据库操作类
附上源代码: using System; using System.Collections.Generic; using System.Data; using System.Linq; using S ...
- C#图解教程 第二十四章 反射和特性
反射和特性 元数据和反射Type 类获取Type对象什么是特性应用特性预定义的保留的特性 Obsolete(废弃)特性Conditional特性调用者信息特性DebuggerStepThrough 特 ...
- C# 利用反射
.NET基础篇——反射的奥妙 C#获取实体类属性名和值 | 遍历类对象 c#通过反射获取类上的自定义特性 C#利用反射+特性实现简单的实体映射数据库操作类
- C#语法——反射,架构师的入门基础。
前言 编程其实就是写代码,而写代码目的就是实现业务,所以,语法和框架也是为了实现业务而存在的.因此,不管多么高大上的目标,实质上都是业务. 所以,我认为不要把写代码上升到科学的高度.上升到艺术就可以了 ...
- FreeSql (三)实体特性
主键(Primary Key) class Topic { [Column(IsPrimary = true)] public int Id { get; set; } } 约定: 当没有指明主键时, ...
- FreeSql (四)实体特性 Fluent Api
FreeSql 提供使用 Fluent Api, 在外部配置实体的数据库特性,Fluent Api 的方法命名与特性名保持一致,如下: fsql.CodeFirst .ConfigEntity< ...
- FreeSql (三十三)CodeFirst 类型映射
前面有介绍过几篇 CodeFirst 内容文章,有 <(二)自动迁移实体>(https://www.cnblogs.com/FreeSql/p/11531301.html) <(三) ...
- FreeSql (三十四)CodeFirst 迁移说明
FreeSql 支持 CodeFirst 迁移结构至数据库,这应该是(O/RM)必须标配的一个功能. 与其他(O/RM)不同FreeSql支持更多的数据库特性,而不只是支持基础的数据类型,这既是优点也 ...
随机推荐
- BZOJ2565 最长双回文串 【Manacher】
BZOJ2565 最长双回文串 Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"c ...
- MAC OS环境下搭建基于Python语言的appium自动化测试环境
#1 安装JDK java -version #2 下载SDK http://adt.android-studio.org/ 下载adt #3 配置sdk环境变量 打开终端,依次输入命令 vim .b ...
- GCD 深入理解(二)
转自@nixzhu的GitHub主页(译者:Riven.@nixzhu),原文<Grand Central Dispatch In-Depth: Part 2/2> 欢迎来到GCD深入理解 ...
- Object-C 中的Selector 概念
selector可以叫做选择器,其实指的就是对象的方法,也可以理解为C语言里面的函数指针,在面向对象里面的对应概念. @selector(xxxx)的作用是找到名字为xxxx的方法.一般用于[a pe ...
- python笔记-9(subprocess模块、面向对象、socket入门)
一.subprocess 模块 1.了解os.system()与os.popen的区别及不足 1.1 os.system()可以执行系统指令,将结果直接输出到屏幕,同时可以将指令是否执行成功的状态赋值 ...
- flask第二十篇——模板【3】
请关注公众号:自动化测试实战 现在我们通过查询字符串的方式给render_template传参,我们就要用到flask库的flask.request.args.get()函数先获取参数,在index. ...
- Sprint第一个冲刺(第二天)
一.Sprint介绍 今天我们完成了欢迎界面及美化的任务,即完成了此次整个Sprint的百分之七,登录界面及美化.注册界面(管理员).注册界面(餐厅员工)和注册界面(消费者),这几个任务也在进行时.这 ...
- [MEF] 学习之一 入门级的简单Demo(转)
MEF 的精髓在于插件式开发,方便扩展. 我学东西,习惯性的先搞的最简单的Demo出来,看看有没有好玩的东东,然后继续深入.这个博文,不谈大道理,看demo说事儿. 至于概念,请google ,大把大 ...
- caddy server 了解
Caddy 是一个Go写的服务器软件,官方的宣传语“The HTTP/2 web server with automatic HTTPS”以及“Serve The Web Like It's 2016 ...
- php系统函数-----数组函数