c#映射数据库中表的实体类

来源:互联网 发布:电视视频通话软件 编辑:程序博客网 时间:2024/05/17 23:09
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data;
using System.IO;
using System.Reflection;


namespace UnitTest
{
    class Program
    {
        static void Main(string[] args)
        {

            #region 读取数据库就绪准备
            string connectionString = "数据库连接";
            SqlConnection con = new SqlConnection(connectionString);
            DataTable dt = new DataTable();
            con.Open(); //打开数据库
            string sql = "SELECT sobj.name as TableName,scol.name as ColumnName,sprop.[value] as Des,sc.name as TypeName,sc.length,scol.isnullable FROM syscolumns as scol inner join sys.sysobjects as sobj on scol.id=sobj.id and sobj.xtype='U' and sobj.name<>'dtproperties' inner join systypes as sc on sc.xusertype=scol.xtype left join sys.extended_properties as sprop on scol.id=sprop.major_id and scol.colid=sprop.minor_id";
            //SqlCommand com = new SqlCommand(sql, con);
            // SqlDataReader read = com.ExecuteReader();
            SqlDataAdapter sda = new SqlDataAdapter(sql, con);
            sda.Fill(dt);
            con.Close();//关闭数据库
            List<string> tableNameArray = new List<string>();
            #endregion
            #region 从数据库读取所有字段名称、字段类型、长度、是否为空、描述
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                var read = dt.Rows[i];
                tableNameArray.Add(Convert.ToString(read["TableName"]));  //将表名保存到列表中
               // Console.WriteLine("表名:" + read["TableName"] + " 字段名称:" + read["ColumnName"] + " 字段描述:" + read["Des"] + " 字段长度:" + read["length"] + " 字段类型:" + read["TypeName"] + " 是否为空:" + read["isnullable"]);
            }
            tableNameArray = tableNameArray.Distinct().ToList();
            int n = 0;
            foreach (string tableName in tableNameArray)
            {
                n= n+ 1;
                DataRow[] dr = dt.Select("TableName='"+ tableName + "'");
                ClassBuilder classBuilder = new ClassBuilder("Model", tableName,dr);
                classBuilder.Execute();
            }


            #endregion
        }


        public class ClassBuilder
        {
            #region 属性
            /// <summary>写入器</summary>
            public StringBuilder StringBuilder = new StringBuilder();
            /// <summary>写入器</summary>
            public TextWriter TextWriter { get; set; }
            /// <summary>数据表</summary>
            public string TableName { get; set; }


            /// <summary>命名空间</summary>
            public string Namespace { get; set; }
            /// <summary>数据行</summary>
            public DataRow[] DataRow { get; set; }


            /// <summary>引用命名空间</summary>
            public HashSet<String> Usings { get; } = new HashSet<String>(StringComparer.OrdinalIgnoreCase);


            /// <summary>纯净类</summary>
            public Boolean Pure { get; set; }


            /// <summary>生成接口</summary>
            public Boolean Interface { get; set; }


            /// <summary>基类</summary>
            public string BaseClass { get; set; }
            public int Indent = 5;//缩进
            public string IndetSpace { get; set; }//缩进空格
            #endregion


            #region 构造
            /// <summary>实例化</summary>
            public ClassBuilder(string nameSpace, string tableName, DataRow[] dr)
            {
                Namespace = nameSpace;
                TableName = tableName;
                DataRow = dr;
                Usings.Add("System");
                Usings.Add("System.Collections.Generic");
                Usings.Add("System.ComponentModel");
                TextWriter = new StringWriter(StringBuilder); //实例化
            }
            #endregion


            #region 主方法
            /// <summary>执行生成</summary>
            public virtual void Execute()
            {
                WriteLine("生成 {0}", TableName);
                //写入文件内容开始
                OnExecuting();
                //字段
                BuildItems();
                //文件内容末尾
                OnExecuted();
                //输出文件
                OutputFile();
            }


            /// <summary>生成头部</summary>
            protected virtual void OnExecuting()
            {
                // 引用命名空间
                var us = Usings.OrderBy(e => e.StartsWith("System") ? 0 : 1).ThenBy(e => e).ToArray();
                foreach (var item in us)
                {
                    TextWriter.WriteLine("using {0};",item);
                   // StringBuilder.Append("using {0};").Append(item);
                }
                TextWriter.WriteLine(); //命名空间和引用之间换行
                // TextWriter.WriteLine();
                if (!string.IsNullOrEmpty(Namespace))
                {
                    TextWriter.WriteLine("namespace {0}", Namespace);
                    TextWriter.WriteLine("{");
                    //StringBuilder.Append("namespace ").Append(Namespace);   //命名空间
                    //StringBuilder.Append("{");
                }
                BuildClassHeader();
            }


            /// <summary>实体类头部</summary>
            protected virtual void BuildClassHeader()
            {
                // 头部
                BuildAttribute();


                // 类名和基类
                var cn = GetClassName();
                if (!string.IsNullOrEmpty(BaseClass)) BaseClass = " : " + BaseClass;


                // 类接口
                if (Interface)
                    WriteLine("public interface {0}{1}", cn, BaseClass);
                else
                    WriteLine("public partial class {0}{1}", cn, BaseClass);
                WriteLine("{");
            }


            /// <summary>获取类名</summary>
            /// <returns></returns>
            protected virtual String GetClassName()
            {
                var name =TableName;
                if (Interface) name = "I" + name;


                return name;
            }


            /// <summary>获取基类</summary>
            /// <returns></returns>


            /// <summary>实体类头部</summary>
            protected virtual void BuildAttribute()
            {
                // 注释
              //  var des = Table.Description;
               // WriteLine("/// <summary>{0}</summary>", des);


                if (!Pure)
                {
                    // WriteLine("[Serializable]");
                    // WriteLine("[DataObject]");
                    //  StringBuilder.Append("[Serializable]");
                    // StringBuilder.Append("[DataObject]");
                    SetIndent(3);//设置缩进空格
                    TextWriter.WriteLine(_Indent+"[Serializable]");
                    TextWriter.WriteLine(_Indent+"[DataObject]");
                    // if (!des.IsNullOrEmpty()) WriteLine("[Description(\"{0}\")]", des);
                }
                TextWriter.WriteLine(_Indent+"public partial class {0}", TableName);
                TextWriter.WriteLine(_Indent+"{");
            }


            /// <summary>生成尾部</summary>
            protected virtual void OnExecuted()
            {
                // 类接口
                // WriteLine("}");
                // StringBuilder.Append("}");
                SetIndent(3);
                TextWriter.WriteLine(_Indent+"}");
                if (!string.IsNullOrEmpty(Namespace))
                {
                    TextWriter.WriteLine("}");
                    //StringBuilder.Append("}");
                    //Writer.Write("}");
                }
            }


            /// <summary>生成主体</summary>
            protected virtual void BuildItems()
            {
                SetIndent(6);
                TextWriter.WriteLine(_Indent+"#region 属性");
               // StringBuilder.Append("#region 属性");
                // WriteLine("#region 属性");
                for (int i = 0; i <DataRow.Count(); i++)
                {
                    if (i > 0) WriteLine();
                    BuildItem(DataRow[i]);
                }
                SetIndent(6);
                TextWriter.WriteLine(_Indent+"#endregion");
               // StringBuilder.Append("#endregion");
                //WriteLine("#endregion");
            }


            /// <summary>生成每一项</summary>
            protected virtual void BuildItem(DataRow dr)
            {
                // var dc = column;
                //BuildItemAttribute(column);
                // 注释
                // var des = dc.Description;
                // WriteLine("/// <summary>{0}</summary>", des);
                // StringBuilder.Append("/// <summary>").Append(Convert.ToString(dr["Des"])).Append("</summary>");
                SetIndent(11);
                TextWriter.WriteLine(_Indent+"///<summary>{0}</summary>", Convert.ToString(dr["Des"]).Replace("\r\n", ""));  //输出字段说明,同时替换换行符
                string type = Convert.ToString(dr["TypeName"]); //数据库中字段类型
                bool isNullAble = Convert.ToBoolean(dr["isnullable"]); //0.不可为空 1.可为空
                string columnType = ChangeToCSharpType(Convert.ToString(dr["TypeName"]));
                if (!isNullAble)
                {
                    TextWriter.WriteLine(_Indent+"public {0} {1} {2}", columnType, dr["ColumnName"], "{ get; set;}");  //字段属性
                    // StringBuilder.Append("      public   ").Append(type).Append("{ get; set; }");
                }
                else {
                    if (columnType != "String")
                    {
                        TextWriter.WriteLine(_Indent + "public {0}? {1} {2}", columnType, dr["ColumnName"], "{ get; set; }"); //字段属性
                    }
                    else {
                        TextWriter.WriteLine(_Indent + "public {0} {1} {2}", columnType, dr["ColumnName"], "{ get; set; }"); //字段属性
                    }
                    
                    // StringBuilder.Append("      public   ").Append(type).Append("?").Append("{ get; set; }");
                }
                


                


                //if (!Pure)
                //{
                //    if (!des.IsNullOrEmpty()) WriteLine("[Description(\"{0}\")]", des);


                //    var dis = dc.DisplayName;
                //    if (!dis.IsNullOrEmpty()) WriteLine("[DisplayName(\"{0}\")]", dis);
                //}


                //var type = dc.Properties["Type"];
                //if (type.IsNullOrEmpty()) type = dc.DataType?.Name;


                //if (Interface)
                //    WriteLine("{0} {1} {{ get; set; }}", type, dc.Name);
                //else
                //    WriteLine("public {0} {1} {{ get; set; }}", type, dc.Name);
            }


            ///// <summary>属性头部特性</summary>
            //protected virtual void BuildItemAttribute(IDataColumn column)
            //{
            //    // 注释
            //    var des = column.Description;
            //    WriteLine("/// <summary>{0}</summary>", des);
            //    if (!des.IsNullOrEmpty()) WriteLine("[Description(\"{0}\")]", des);


            //    WriteLine("[Serializable]");
            //    WriteLine("[DataObject]");
            //}
            #endregion


            #region 写入缩进方法
            private string _Indent;


            /// <summary>设置缩进</summary>
            /// <param name="add"></param>
            protected virtual void SetIndent(int indentNumber)
            {
                    _Indent = "               ";
                if (indentNumber <= 15) //空格长度为15
                {   
                    _Indent = _Indent.Substring(0, indentNumber);
                }
                else {
                    _Indent = "";
                }
            }


            /// <summary>写入</summary>
            /// <param name="value"></param>
            protected virtual void WriteLine(String value = null)
            {
                if (string.IsNullOrEmpty(value))
                {
                   // Writer.WriteLine();
                    return;
                }
                var v = value;
                if (!string.IsNullOrEmpty(_Indent)) v = _Indent + v;


              //  Writer.WriteLine(v);
            }


            /// <summary>写入</summary>
            /// <param name="format"></param>
            /// <param name="args"></param>
            protected virtual void WriteLine(String format, params Object[] args)
            {
                if (!string.IsNullOrEmpty(_Indent)) format = _Indent + format;


               // Writer.WriteLine(format, args);
            }


            /// <summary>清空,重新生成</summary>
            public void Clear()
            {
                _Indent = null;


                //var sw = Writer as StringWriter;
                //if (sw != null)
                //{
                //    sw.GetStringBuilder().Clear();
                //}
            }


            /// <summary>输出结果</summary>
            /// <returns></returns>
            //public override String ToString()
            //{
            //    return Writer.ToString();
            //}
            #endregion


            #region 保存
            /// <summary>输出目录</summary>
            public String Output { get; set; }


            /// <summary>保存文件,返回文件路径</summary>
            public virtual void OutputFile(String ext = null, Boolean overwrite = true)
            {
                BuilderHelp pathBuilder = new BuilderHelp();


                string path = pathBuilder.Path + TableName + pathBuilder.Suffix;
                //if (File.Exists(path)) //文件存在,先清除内容
                //{
                //    File.Delete(path);
                //}
                using (StreamWriter tw = new StreamWriter(path))  //如果原文件已存在,则会覆盖原文件内容
                {
                    tw.WriteLine(StringBuilder.ToString());
                    // Console.WriteLine(tw.BaseStream.GetType());     //输出FileStream
                }


                //var p = Output;
                ////if (Table.Properties.ContainsKey("Output")) p = p.CombinePath(Table.Properties["Output"]);
                ////if (Table.Properties.ContainsKey("分类")) p = p.CombinePath(Table.Properties["分类"]);


                //if (ext.IsNullOrEmpty()) ext = ".cs";


                //if (Interface)
                //    p = p.CombinePath("I" + Table.Name + ext);
                //else if (!Table.DisplayName.IsNullOrEmpty())
                //    p = p.CombinePath(Table.DisplayName + ext);
                //else
                //    p = p.CombinePath(Table.Name + ext);


                //p = p.GetFullPath();


                //if (!File.Exists(p) || overwrite) File.WriteAllText(p.EnsureDirectory(true), ToString());


                //return p;
            }
            #endregion


            #region 辅助
            /// <summary>C#版本</summary>
            public Version CSharp { get; set; }


            /// <summary>nameof</summary>
            /// <param name="name"></param>
            /// <returns></returns>
            //protected String NameOf(String name)
            //{
            //    var v = CSharp;
            //    if (v == null || v.Major == 0 || v.Major > 5) return "nameof({0})".F(name);


            //    return "\"" + name + "\"";
            //}


            /// <summary>是否调试</summary>
            public static Boolean Debug { get; set; }






            /// <summary>写日志</summary>
            /// <param name="format"></param>
            /// <param name="args"></param>
            //public void WriteLog(String format, params Object[] args)
            //{
            //    Log?.Info(format, args);
            //}
            #endregion




            /// <summary>
            /// 数据库中与C#中的数据类型对照
            /// </summary>
            /// <param name="type"></param>
            /// <returns></returns>
            private string ChangeToCSharpType(string type)
            {
                string reval = string.Empty;
                switch (type.ToLower())
                {
                    case "int":
                        reval = "Int32";
                        break;
                    case "text":
                        reval = "String";
                        break;
                    case "bigint":
                        reval = "Int64";
                        break;
                    case "binary":
                        reval = "System.Byte[]";
                        break;
                    case "bit":
                        reval = "Boolean";
                        break;
                    case "char":
                        reval = "String";
                        break;
                    case "datetime":
                        reval = "System.DateTime";
                        break;
                    case "decimal":
                        reval = "System.Decimal";
                        break;
                    case "float":
                        reval = "System.Double";
                        break;
                    case "image":
                        reval = "System.Byte[]";
                        break;
                    case "money":
                        reval = "System.Decimal";
                        break;
                    case "nchar":
                        reval = "String";
                        break;
                    case "ntext":
                        reval = "String";
                        break;
                    case "numeric":
                        reval = "System.Decimal";
                        break;
                    case "nvarchar":
                        reval = "String";
                        break;
                    case "real":
                        reval = "System.Single";
                        break;
                    case "smalldatetime":
                        reval = "System.DateTime";
                        break;
                    case "smallint":
                        reval = "Int16";
                        break;
                    case "smallmoney":
                        reval = "System.Decimal";
                        break;
                    case "timestamp":
                        reval = "System.DateTime";
                        break;
                    case "tinyint":
                        reval = "System.Byte";
                        break;
                    case "uniqueidentifier":
                        reval = "System.Guid";
                        break;
                    case "varbinary":
                        reval = "System.Byte[]";
                        break;
                    case "varchar":
                        reval = "String";
                        break;
                    case "Variant":
                        reval = "Object";
                        break;
                    default:
                        reval = "String";
                        break;
                }
                return reval;
            }


        }






        public class BuilderHelp
        {
            /// <summary> 输出路径 </summary>
            public string Path { get { return @"E:\测试VS\wcf\WcfService1Main\Model\"; } }
            /// <summary> 输出文件后缀</summary>
            public string Suffix { get { return ".cs"; } }
        }


    }
}