C# ORM學習筆記:使用特性+反射實現簡單ORM

    1、原理與環境

    在生成數據表的實體類時,利用自定義特性,給它打上表及字段的特性,而後使用反射原理,將自定義特性拼接成增、刪、改、查對應的SQL,便可完成一個簡單的ORM。數據庫

    本示例的執行環境:緩存

    1)數據庫:SQL Server。(可根據本身的須要,創建不一樣的數據庫工廠。)架構

    2)數據表:需使用自增類型(identity)做爲數據表的主鍵。主鍵名字能夠隨便起,如ID。ide

    3)實體類:實體類需提供無參構造函數。函數

    2、演示數據表

    Person表,包含主鍵(ID)、姓名(Name)、年齡(Age)、性別(Gender)。測試

CREATE TABLE [dbo].[Person](    [ID] [BIGINT] IDENTITY(1,1) NOT NULL,    [Name] [NVARCHAR](50) NULL,    [Age] [INT] NULL,    [Gender] [NVARCHAR](10) NULL, CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED (    [ID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]

    2、自定義特性

    定義兩個自定義特性:ui

    2.一、DataTableAttribute

    此爲數據表特性,包含表名(TableName)、主鍵(Key)。this

    [Serializable]    public class DataTableAttribute : Attribute
    {        /// 
        /// 數據表        /// 
        public string TableName { get; }        /// 
        /// 主鍵        /// 
        public string Key { get; }        /// 
        /// 構造函數        /// 
        /// 
        /// 
        public DataTableAttribute(string tableName, string key)
        {
            TableName = tableName;
            Key = key;
        }
    }

    2.二、DataFieldAttribute

    此爲字段特性,包含字段名(FieldName)、字段類型(FieldType)、長度(Length)、是否自增(IsIdentity)。spa

    [Serializable]    public class DataFieldAttribute : Attribute
    {        public string FieldName { get; set; }        public string FieldType { get; set; }        public int Length { get; set; }        public bool IsIdentity { get; set; }        /// 
        /// 構造函數        /// 
        /// 字段名
        /// 字段類型
        /// 長度
        /// 是否自增加
        public DataFieldAttribute(string fieldName, string fieldType, int length, bool isIdentity)
        {
            FieldName = fieldName;
            FieldType = fieldType;
            Length = length;
            IsIdentity = isIdentity;
        }        /// 
        /// 構造函數        /// 
        /// 
        /// 
        /// 
        public DataFieldAttribute(string fieldName, string fieldType, int length) : this(fieldName, fieldType, length, false)
        { }        /// 
        /// 構造函數        /// 
        /// 
        /// 
        public DataFieldAttribute(string fieldName, string fieldType) : this(fieldName, fieldType, 0, false)
        { }        /// 
        /// 構造函數        /// 
        /// 
        /// 
        public DataFieldAttribute(string fieldName, bool isIdentity) : this(fieldName, "", 0, isIdentity)
        { }        /// 
        /// 構造函數        /// 
        /// 
        public DataFieldAttribute(string fieldName) : this(fieldName, false)
        { }
    }

    3、生成實體類

    3.一、實體類樣式

    依照前面的規劃,Person表須要生成下面這個樣子:debug

using System;using System.Collections.Generic;using System.Text;using LinkTo.ORM.CustomAttribute;namespace LinkTo.ORM.Model
{
    [DataTable("Person","ID")]
    [Serializable]    public class Person
    {        public Person() { }

        [DataField("ID","bigint",19,true)]        public long? ID {get; set;}

        [DataField("Name","nvarchar",50,false)]        public string Name {get; set;}

        [DataField("Age","int",10,false)]        public int? Age {get; set;}

        [DataField("Gender","nvarchar",10,false)]        public string Gender {get; set;}
    }
}

    3.二、使用T4模板生成實體類

    3.2.一、T4Code文件夾的文本模板

<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data"#>
<#@ import namespace="System.Data.SqlClient"#>
<#+    #region T4Code    /// 
    /// 數據庫架構接口    /// 
    public interface IDBSchema : IDisposable
    {
        List<string> GetTableList();
        DataTable GetTableMetadata(string tableName);
    }    /// 
    /// 數據庫架構工廠    /// 
    public class DBSchemaFactory
    {        static readonly string DatabaseType = "SqlServer";        public static IDBSchema GetDBSchema()
        {
            IDBSchema dbSchema;            switch (DatabaseType) 
            {                case "SqlServer":
                    {
                        dbSchema =new SqlServerSchema();                        break;
                    }                default: 
                    {                        throw new ArgumentException("The input argument of DatabaseType is invalid.");
                    }
            }            return dbSchema;
        }
    }    /// 
    /// SqlServer    /// 
    public class SqlServerSchema : IDBSchema
    {        public string ConnectionString = "Server=.;Database=Test;Uid=sa;Pwd=********;";        public SqlConnection conn;        public SqlServerSchema()
        {
            conn = new SqlConnection(ConnectionString);
            conn.Open();
        }        public List<string> GetTableList()
        {
            List<string> list = new List<string>();            string commandText = "SELECT NAME TABLE_NAME FROM SYSOBJECTS WHERE XTYPE='U' ORDER BY NAME";            using(SqlCommand cmd = new SqlCommand(commandText, conn))
            {                using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                {                    while (dr.Read())
                    {
                        list.Add(dr["TABLE_NAME"].ToString());
                    }
                }
            }            return list;
        }        
        public DataTable GetTableMetadata(string tableName)
        {            string commandText=string.Format
                (                    "SELECT A.NAME TABLE_NAME,B.NAME FIELD_NAME,C.NAME DATATYPE,ISNULL(B.PREC,0) LENGTH, "+                        "CONVERT(BIT,CASE WHEN NOT F.ID IS NULL THEN 1 ELSE 0 END) ISKEY, "+                        "CONVERT(BIT,CASE WHEN COLUMNPROPERTY(B.ID,B.NAME,'ISIDENTITY') = 1 THEN 1 ELSE 0 END) AS ISIDENTITY, "+                        "CONVERT(BIT,B.ISNULLABLE) ISNULLABLE "+                    "FROM SYSOBJECTS A INNER JOIN SYSCOLUMNS B ON A.ID=B.ID INNER JOIN SYSTYPES C ON B.XTYPE=C.XUSERTYPE "+                        "LEFT JOIN SYSOBJECTS D ON B.ID=D.PARENT_OBJ AND D.XTYPE='PK' "+                        "LEFT JOIN SYSINDEXES E ON B.ID=E.ID AND D.NAME=E.NAME "+                        "LEFT JOIN SYSINDEXKEYS F ON B.ID=F.ID AND B.COLID=F.COLID AND E.INDID=F.INDID "+                    "WHERE A.XTYPE='U' AND A.NAME='{0}' "+                    "ORDER BY A.NAME,B.COLORDER", tableName
                );            using(SqlCommand cmd = new SqlCommand(commandText, conn))
            {
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                DataSet ds = new DataSet();
                da.Fill(ds,"Schema");                return ds.Tables[0];
            }
        }        public void Dispose()
        {            if (conn != null)
            {
                conn.Close();
            }
        }
    }    #endregion#>

DBSchema.ttinclude

<#@ assembly name="System.Core" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data"#>
<#@ import namespace="System.IO"#>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating"#>

<#+// T4 Template Block manager for handling multiple file outputs more easily.// Copyright (c) Microsoft Corporation.All rights reserved.// This source code is made available under the terms of the Microsoft Public License (MS-PL)// Manager class records the various blocks so it can split them upclass Manager
{    public struct Block
    {        public string Name;        public int Start, Length;
    }    public Listblocks = new List();    public Block currentBlock;    public Block footerBlock = new Block();    public Block headerBlock = new Block();    public ITextTemplatingEngineHost host;    public ManagementStrategy strategy;    public StringBuilder template;    public string OutputPath { get; set; }    public Manager(ITextTemplatingEngineHost host, StringBuilder template, bool commonHeader)
    {        this.host = host;        this.template = template;
        OutputPath = string.Empty;
        strategy = ManagementStrategy.Create(host);
    }    public void StartBlock(string name)
    {
        currentBlock = new Block { Name = name, Start = template.Length };
    }    public void StartFooter()
    {
        footerBlock.Start = template.Length;
    }    public void EndFooter()
    {
        footerBlock.Length = template.Length - footerBlock.Start;
    }    public void StartHeader()
    {
        headerBlock.Start = template.Length;
    }    public void EndHeader()
    {
        headerBlock.Length = template.Length - headerBlock.Start;
    }    

    public void EndBlock()
    {
        currentBlock.Length = template.Length - currentBlock.Start;
        blocks.Add(currentBlock);
    }    public void Process(bool split)
    {        string header = template.ToString(headerBlock.Start, headerBlock.Length);        string footer = template.ToString(footerBlock.Start, footerBlock.Length);
        blocks.Reverse();        foreach(Block block in blocks) {            string fileName = Path.Combine(OutputPath, block.Name);            if (split) {                string content = header + template.ToString(block.Start, block.Length) + footer;
                strategy.CreateFile(fileName, content);
                template.Remove(block.Start, block.Length);
            } else {
                strategy.DeleteFile(fileName);
            }
        }
    }
}class ManagementStrategy
{    internal static ManagementStrategy Create(ITextTemplatingEngineHost host)
    {        return (host is IServiceProvider) ? new VSManagementStrategy(host) : new ManagementStrategy(host);
    }    internal ManagementStrategy(ITextTemplatingEngineHost host) { }    internal virtual void CreateFile(string fileName, string content)
    {
        File.WriteAllText(fileName, content);
    }    internal virtual void DeleteFile(string fileName)
    {        if (File.Exists(fileName))
            File.Delete(fileName);
    }
}class VSManagementStrategy : ManagementStrategy
{    private EnvDTE.ProjectItem templateProjectItem;    internal VSManagementStrategy(ITextTemplatingEngineHost host) : base(host)
    {
        IServiceProvider hostServiceProvider = (IServiceProvider)host;        if (hostServiceProvider == null)            throw new ArgumentNullException("Could not obtain hostServiceProvider");

        EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));        if (dte == null)            throw new ArgumentNullException("Could not obtain DTE from host");

        templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile);
    }    internal override void CreateFile(string fileName, string content)
    {        base.CreateFile(fileName, content);
        ((EventHandler)delegate { templateProjectItem.ProjectItems.AddFromFile(fileName); }).BeginInvoke(null, null, null, null);
    }    internal override void DeleteFile(string fileName)
    {
        ((EventHandler)delegate { FindAndDeleteFile(fileName); }).BeginInvoke(null, null, null, null);
    }    private void FindAndDeleteFile(string fileName)
    {        foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems)
        {            if (projectItem.get_FileNames(0) == fileName)
            {
                projectItem.Delete();                return;
            }
        }
    }
}
#>

MultiDocument.ttinclude

    DBSchema.ttinclude主要實現了數據庫工廠的功能。注:請將數據庫鏈接字符串改爲您本身的。

    MultiDocument.ttinclude主要實現了多文檔的功能。

    3.2.二、生成實體類的文本模板

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ include file="T4Code/DBSchema.ttinclude"#>
<#@ include file="T4Code/MultiDocument.ttinclude"#>
<# var manager = new Manager(Host, GenerationEnvironment, true) { OutputPath = Path.GetDirectoryName(Host.TemplateFile)}; #>
<#    //System.Diagnostics.Debugger.Launch();//調試
    var dbSchema = DBSchemaFactory.GetDBSchema();
    List<string> tableList = dbSchema.GetTableList();    foreach (string tableName in tableList)
    {
        manager.StartBlock(tableName+".cs");
        DataTable table = dbSchema.GetTableMetadata(tableName);        //獲取主鍵
        string strKey = string.Empty;        foreach (DataRow dataRow in table.Rows)
        {            if ((bool)dataRow["ISKEY"] == true)
            {
                strKey = dataRow["FIELD_NAME"].ToString();                break;
            }
        }
        
#>//-------------------------------------------------------------------------------// 此代碼由T4模板MultModelAuto自動生成// 生成時間 // 對此文件的更改可能會致使不正確的行爲,而且若是從新生成代碼,這些更改將會丟失。//-------------------------------------------------------------------------------using System;using System.Collections.Generic;using System.Text;using LinkTo.ORM.CustomAttribute;namespace LinkTo.ORM.Model
{
    [DataTable("","")]
    [Serializable]    public class 
    {        public () { }<#        foreach (DataRow dataRow in table.Rows)
        {            //獲取數據類型
            string dbDataType = dataRow["DATATYPE"].ToString();            string dataType = string.Empty;                    
            switch (dbDataType)
            {                case "decimal":                case "numeric":                case "money":                case "smallmoney":
                    dataType = "decimal?";                    break;                case "char":                case "nchar":                case "varchar":                case "nvarchar":                case "text":                case "ntext":
                    dataType = "string";                    break;                case "uniqueidentifier":
                    dataType = "Guid?";                    break;                case "bit":
                    dataType = "bool?";                    break;                case "real":
                    dataType = "Single?";                    break;                case "bigint":
                    dataType = "long?";                    break;                case "int":
                    dataType = "int?";                    break;                case "tinyint":                case "smallint":
                    dataType = "short?";                    break;                case "float":
                    dataType = "float?";                    break;                case "date":                case "datetime":                case "datetime2":                case "smalldatetime":
                    dataType = "DateTime?";                    break;                case "datetimeoffset ":
                    dataType = "DateTimeOffset?";                    break;                case "timeSpan ":
                    dataType = "TimeSpan?";                    break;                case "image":                case "binary":                case "varbinary":
                    dataType = "byte[]";                    break;                default:                    break;
            }
#>

        [DataField("<#= dataRow["FIELD_NAME"].ToString() #>","<#= dataRow["DATATYPE"].ToString() #>",<#= dataRow["LENGTH"].ToString() #>,<#= dataRow["ISIDENTITY"].ToString().ToLower() #>)]        public  <#= dataRow["FIELD_NAME"].ToString() #> {get; set;}<#
        }
#>
    }
}<#
        manager.EndBlock();
    }
    dbSchema.Dispose();
    manager.Process(true);
#>

MultiModelAuto.tt

    注:因爲ORM拼接SQL時使用的是表特性及字段特性,能夠看出表特性上使用的表名、字段特性上使用的字段名,都是與數據庫一致的。有了這個保障,數據表生成實體類的時候,類名是能夠更改的,由於我只須要保證表特性與數據庫一致便可。舉個例子,我有個數據表Person_A,在生成實體類時,類名能夠生成爲Class PersonA {...},可是表特性依然是[DataTable("Person_A","...")]。相同的原理,屬性名也是能夠更改的。

    4、ORM實現

    數據表的CURD,主要是經過反射來實現SQL拼接,實現以下:

using System;using System.Collections;using System.Collections.Generic;using System.Data;using System.Data.SqlClient;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;using LinkTo.ORM.CustomAttribute;namespace LinkTo.ORM
{    public static class DBHelper
    {        public static readonly string ConnectionString = "Server=.;Database=Test;Uid=sa;Pwd=********;";        private static readonly Hashtable _HashTableName = new Hashtable(); //表名緩存
        private static readonly Hashtable _HashKey = new Hashtable();       //主鍵緩存

        /// 
        /// 數據庫鏈接        /// 
        /// 
        public static SqlConnection GetConnection()
        {
            SqlConnection conn = new SqlConnection(ConnectionString);            return conn;
        }        /// 
        /// 新增        /// 
        /// 
        /// 
        /// 
        public static int Insert(TEntity entity) where TEntity : class
        {            string strTableName = "";                                   //表名
            string strInsertSQL = "INSERT INTO {0} ({1}) VALUES ({2})"; //SQL拼接語句            //獲取表名
            strTableName = GetTableName(entity);            //獲取字段列表及值列表
            StringBuilder strFields = new StringBuilder();
            StringBuilder strValues = new StringBuilder();
            ListparaList = new List();

            PropertyInfo[] infos = entity.GetType().GetProperties();
            DataFieldAttribute dfAttr = null;            object[] dfAttrs;            int i = 0;            foreach (PropertyInfo info in infos)
            {
                dfAttrs = info.GetCustomAttributes(typeof(DataFieldAttribute), false);                if (dfAttrs.Length > 0)
                {
                    dfAttr = dfAttrs[0] as DataFieldAttribute;                    if (dfAttr is DataFieldAttribute)
                    {                        //自增字段不做處理
                        if (dfAttr.IsIdentity) continue;

                        strFields.Append(i > 0 ? "," + dfAttr.FieldName : dfAttr.FieldName);
                        strValues.Append(i > 0 ? "," + "@" + dfAttr.FieldName : "@" + dfAttr.FieldName);
                        i++;
                        paraList.Add(new SqlParameter("@" + dfAttr.FieldName, info.GetValue(entity, null)));
                    }
                }
            }            //格式化SQL拼接語句
            string[] args = new string[] { strTableName, strFields.ToString(), strValues.ToString() };
            strInsertSQL = string.Format(strInsertSQL, args);            //執行結果
            int result = 0;            try
            {                using (SqlConnection conn = GetConnection())
                {
                    conn.Open();                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.CommandText = strInsertSQL;
                        cmd.CommandType = CommandType.Text;
                        cmd.Connection = conn;                        if (paraList != null)
                        {                            foreach (SqlParameter param in paraList)
                            {
                                cmd.Parameters.Add(param);
                            }
                        }
                        result = cmd.ExecuteNonQuery();
                    }
                }
            }            catch (Exception ex)
            {                throw new Exception(ex.ToString());
            }            //返回影響行數
            return result;
        }        /// 
        /// 刪除        /// 
        /// 
        /// 
        /// 
        public static int Delete(string condition) where TEntity : class, new()
        {            string strTableName = "";                           //表名
            string strDeleteSQL = "DELETE FROM {0} WHERE {1}";  //SQL拼接語句            //獲取表名
            strTableName = GetTableName(new TEntity());            //格式化SQL拼接語句
            string[] args = new string[] { strTableName, condition };
            strDeleteSQL = string.Format(strDeleteSQL, args);            //執行結果
            int result = 0;            try
            {                using (SqlConnection conn = GetConnection())
                {
                    conn.Open();                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.CommandText = strDeleteSQL;
                        cmd.CommandType = CommandType.Text;
                        cmd.Connection = conn;
                        result = cmd.ExecuteNonQuery();
                    }
                }
            }            catch (Exception ex)
            {                throw new Exception(ex.ToString());
            }            //返回影響行數
            return result;
        }        /// 
        /// 更新        /// 
        /// 
        /// 
        /// 
        public static int Update(TEntity entity) where TEntity : class
        {            string strTableName = "";                               //表名
            string strUpdateSQL = "UPDATE {0} SET {1} WHERE {2}";   //SQL拼接語句
            string strKey = "";                                     //主鍵
            string strWhere = "";                                   //條件            //獲取表名及主鍵
            strTableName = GetTableName(entity);
            strKey = GetKey(entity);            //獲取更新列表
            StringBuilder strSET = new StringBuilder();
            ListparaList = new List();

            PropertyInfo[] infos = entity.GetType().GetProperties();
            DataFieldAttribute dfAttr = null;            object[] dfAttrs;            int i = 0;            foreach (PropertyInfo info in infos)
            {
                dfAttrs = info.GetCustomAttributes(typeof(DataFieldAttribute), false);                if (dfAttrs.Length > 0)
                {
                    dfAttr = dfAttrs[0] as DataFieldAttribute;                    if (dfAttr is DataFieldAttribute)
                    {                        //條件處理
                        if (dfAttr.FieldName == strKey)
                        {
                            strWhere = strKey + "=" + info.GetValue(entity, null);
                        }                        //自增字段不做處理
                        if (dfAttr.IsIdentity) continue;

                        strSET.Append(i > 0 ? "," + dfAttr.FieldName + "=@" + dfAttr.FieldName : dfAttr.FieldName + "=@" + dfAttr.FieldName);
                        i++;
                        paraList.Add(new SqlParameter("@" + dfAttr.FieldName, info.GetValue(entity, null)));
                    }
                }
            }            //格式化SQL拼接語句
            string[] args = new string[] { strTableName, strSET.ToString(), strWhere };
            strUpdateSQL = string.Format(strUpdateSQL, args);            //執行結果
            int result = 0;            try
            {                using (SqlConnection conn = GetConnection())
                {
                    conn.Open();                    using (SqlCommand cmd = new SqlCommand())
                    {
                        cmd.CommandText = strUpdateSQL;
                        cmd.CommandType = CommandType.Text;
                        cmd.Connection = conn;                        if (paraList != null)
                        {                            foreach (SqlParameter param in paraList)
                            {
                                cmd.Parameters.Add(param);
                            }
                        }
                        result = cmd.ExecuteNonQuery();
                    }
                }
            }            catch (Exception ex)
            {                throw new Exception(ex.ToString());
            }            //返回影響行數
            return result;
        }        /// 
        /// 查詢        /// 
        /// 
        /// 
        /// 
        public static ListQuery(string condition) where TEntity : class, new()
        {            string strTableName = "";                               //表名
            string strSelectSQL = "SELECT * FROM {0} WHERE {1}";    //SQL拼接語句
            Listlist = new List();               //實體列表            //獲取表名
            strTableName = GetTableName(new TEntity());            //格式化SQL拼接語句
            string[] args = new string[] { strTableName, condition };
            strSelectSQL = string.Format(strSelectSQL, args);            //獲取實體列表
            PropertyInfo[] infos = typeof(TEntity).GetProperties();
            DataFieldAttribute dfAttr = null;            object[] dfAttrs;            try
            {                using (SqlConnection conn = GetConnection())
                {
                    conn.Open();                    using (SqlCommand cmd = new SqlCommand(strSelectSQL, conn))
                    {                        using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                        {                            while (dr.Read())
                            {
                                TEntity entity = new TEntity();                                foreach (PropertyInfo info in infos)
                                {
                                    dfAttrs = info.GetCustomAttributes(typeof(DataFieldAttribute), false);                                    if (dfAttrs.Length > 0)
                                    {
                                        dfAttr = dfAttrs[0] as DataFieldAttribute;                                        if (dfAttr is DataFieldAttribute)
                                        {
                                            info.SetValue(entity, dr[dfAttr.FieldName]);
                                        }
                                    }
                                }
                                list.Add(entity);
                            }
                        }
                    }
                }
            }            catch (Exception ex)
            {                throw new Exception(ex.ToString());
            }            //返回實體列表
            return list;
        }        /// 
        /// 根據實體返回表名        /// 
        /// 
        /// 
        public static string GetTableName(TEntity entity) where TEntity : class
        {
            Type entityType = entity.GetType();            string strTableName = Convert.ToString(_HashTableName[entityType.FullName]);            if (strTableName == "")
            {                if (entityType.GetCustomAttributes(typeof(DataTableAttribute), false)[0] is DataTableAttribute dtAttr)
                {
                    strTableName = dtAttr.TableName;
                }                else
                {                    throw new Exception(entityType.ToString() + "未設置DataTable特性。");
                }

                _HashTableName[entityType.FullName] = strTableName;
            }            return strTableName;
        }        /// 
        /// 根據實體返回主鍵        /// 
        /// 
        /// 
        public static string GetKey(TEntity entity) where TEntity : class
        {
            Type entityType = entity.GetType();            string strKey = Convert.ToString(_HashKey[entityType.FullName]);            if (strKey == "")
            {                if (entityType.GetCustomAttributes(typeof(DataTableAttribute), false)[0] is DataTableAttribute dtAttr)
                {
                    strKey = dtAttr.Key;
                }                else
                {                    throw new Exception(entityType.ToString() + "未設置DataTable特性。");
                }

                _HashKey[entityType.FullName] = strKey;
            }            return strKey;
        }
    }
}

DBHelper.cs

    5、運行測試

    新建一個控制檯程序:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using LinkTo.ORM.Model;namespace LinkTo.ORM.Client
{    class Program
    {        static void Main()
        {            //新增
            Person insertPerson = new Person
            {
                Name = "Hello",
                Age = 18,
                Gender = "male"
            };            int insertResult = DBHelper.Insert(insertPerson);
            Console.WriteLine($"共新增了 {insertResult} 條記錄。");            //更新
            ListupdateList = DBHelper.Query("Name='Hello'");            int updateResult = 0;            if (updateList.Count > 0)
            {                foreach (var item in updateList)
                {
                    Person updatePerson = item;
                    updatePerson.Age = 19;
                    updateResult += DBHelper.Update(updatePerson);
                }
            }
            Console.WriteLine($"共更新了 {updateResult} 條記錄。");            //查詢
            ListselectList = DBHelper.Query("Name='Hello'");            if (selectList.Count > 0)
            {                foreach (var item in selectList)
                {
                    Console.WriteLine("person.Name = " + item.Name);
                    Console.WriteLine("person.Age = " + item.Age);
                    Console.WriteLine("person.Gender = " + item.Gender);
                }
            }            //刪除
            int deleteResult = DBHelper.Delete("Name='Hello'");
            Console.WriteLine($"共刪除了 {deleteResult} 條記錄。");

            Console.Read();
        }
    }
}

Program.cs

    運行結果以下:

相關文章
相關標籤/搜索