07
2016
06

MySql生成.Net中Model类的存储过程

最近用MySQL,花时间写了一个过程用来生成EF的model类,有注释,挺方便,用EF类Entity自动生成的没有字段注释。


要用到的函数:

DELIMITER $$  
DROP FUNCTION IF EXISTS `fun_GetCSTypeFromDbType`$$  
CREATE FUNCTION `fun_GetCSTypeFromDbType`(#本函数不需要在线上执行  
dbtype VARCHAR(50)  
)  
    RETURNS VARCHAR(50)  
      
    BEGIN  
    DECLARE ret VARCHAR(50);  
    IF dbtype='nvarchar' OR dbtype='varchar' OR dbtype='text'   
        THEN SET ret='string';  
    ELSEIF dbtype='datetime' OR dbtype='date'   
        THEN SET ret='DateTime';  
    ELSEIF dbtype='bit'   
        THEN SET ret='bool';  
    ELSEIF dbtype='bigint'   
        THEN SET ret='long';  
    ELSE SET ret=dbtype;  
    END IF;  
    RETURN ret;  
    END$$  
  
DELIMITER ;  
/*  
select fun_GetCSTypeFromDbType('bit');  
*/



存储过程:

DELIMITER $$  
DROP PROCEDURE IF EXISTS `P_GenerateModel`$$  
CREATE PROCEDURE `P_GenerateModel`(##本存储过程不会在程序中调用,不需在线上执行,调用了函数 fun_GetCSTypeFromDbType 如果在其他库执行要注意,author:pukuimin  
tableSchema VARCHAR(50),-- 用到的数据库  
tableName VARCHAR(50) #要生成的类名  
)  
  
BEGIN  
DECLARE count1_1 INT;  
DECLARE retString VARCHAR(8000);  
DECLARE table_name1,column_Name1,is_nullable1,data_type1,character_maximum_length1,column_comment1,Column_Key1 VARCHAR(100);  
DECLARE REFERENCED_TABLE_NAME1,REFERENCED_COLUMN_NAME1 VARCHAR(100);  
DECLARE pri_Column_Name,pri_data_type VARCHAR(100);  
-- 需要定义接收游标数据的变量   
-- 遍历数据结束标志  
DECLARE done INT DEFAULT 0;  
DECLARE cur CURSOR FOR SELECT table_name,column_Name,is_nullable,data_type,character_maximum_length,column_comment,Column_Key FROM information_schema.COLUMNS WHERE table_schema=tableSchema AND table_name = tableName;  
  
DECLARE cur2 CURSOR FOR SELECT table_name,column_name,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE table_schema=tableSchema AND table_name = tableName;  
  
-- 将结束标志绑定到游标  
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;  
SET retString = ''; #初始化为空串  
SET retString=CONCAT(retString,'namespace YCF.Stock.Core.Entities  
{  
    using Abp.Domain.Entities;  
    using System;  
    using System.Collections.Generic;  
    using System.ComponentModel.DataAnnotations;  
    using System.ComponentModel.DataAnnotations.Schema;  
    using YCF.Stock.Core.Enum;  
');  
SET retString=CONCAT(retString,'    [Table("',tableName,'")]',CHAR(10));  
  
  
SELECT column_Name,data_type INTO pri_Column_Name, pri_data_type FROM information_schema.COLUMNS WHERE table_schema=tableSchema AND table_name = tableName AND Column_Key='PRI' LIMIT 1;  
SET retString=CONCAT(retString,'    public partial class ',tableName,' : Entity<',fun_GetCSTypeFromDbType(pri_data_type),'>',CHAR(10));  
SET retString=CONCAT(retString,'    {',CHAR(10));  
#set retString=CONCAT(retString,'//    priName:',pri_Column_Name,',priType:',pri_data_type,char(10));  
  
-- 打开游标  
OPEN cur;  
    
-- 开始循环  
read_loop: LOOP  
    -- 提取游标里的数据,这里只有一个,多个的话也一样;  
    FETCH cur INTO table_name1,column_Name1,is_nullable1,data_type1,character_maximum_length1,column_comment1,Column_Key1;  
    -- 声明结束的时候  
    IF done=1 THEN  
      LEAVE read_loop;  
    END IF;  
    -- 这里做你想做的循环的事件  
    #set retString=CONCAT(retString,'',CHAR(10));  
    SET retString=CONCAT(retString,'  
        /// <summary>  
        /// ',column_comment1,'  
        /// </summary>  
');  
IF data_type1='varchar' OR data_type1='varchar' THEN   
    SET retString=CONCAT(retString,'        [StringLength(',character_maximum_length1,')]  
        [MaxLength(',character_maximum_length1,')]',CHAR(10));  
ELSEIF data_type1='date' OR data_type1='bit' THEN   
    SET retString=CONCAT(retString,'        [Column(TypeName = "',data_type1,'")]',CHAR(10));  
END IF;  
IF Column_Key1='PRI' THEN   
    SET retString=CONCAT(retString,'        [Column("',column_Name1,'")]',CHAR(10),'        public override ',fun_GetCSTypeFromDbType(data_type1),' Id { get; set; }',CHAR(10));  
ELSE  
    SET retString=CONCAT(retString,'        public ',fun_GetCSTypeFromDbType(data_type1),CASE WHEN is_nullable1 ='YES' THEN '?' ELSE '' END,' ',column_Name1,' { get; set; }',CHAR(10));  
END IF;  
  
  
END LOOP;  
  -- 关闭游标  
CLOSE cur;  
SET done=0;#重新把done标识为0,开始第二个游标  
SET retString=CONCAT(retString,'/*',CHAR(10));  
  -- 打开游标2  
OPEN cur2;  
-- 开始循环  
  read_loop2: LOOP  
      -- 提取游标里的数据,这里只有一个,多个的话也一样;  
    FETCH cur2 INTO table_name1,column_Name1,REFERENCED_TABLE_NAME1,REFERENCED_COLUMN_NAME1;  
    -- 声明结束的时候  
    IF done=1 THEN  
      LEAVE read_loop2;  
    END IF;  
    -- 这里做你想做的循环的事件  
    #set retString=CONCAT(retString,'',CHAR(10));  
    IF REFERENCED_TABLE_NAME1 IS NOT NULL THEN   
    SET retString=CONCAT(retString,'        public virtual ',REFERENCED_TABLE_NAME1,' ',REFERENCED_TABLE_NAME1,' { get; set; }',CHAR(10));  
    END IF;  
  END LOOP;  
    -- 关闭游标2  
CLOSE cur2;  
SET retString=CONCAT(retString,'/*',CHAR(10));  
  SET retString=CONCAT(retString,'#warning 因数据库表名全部自动小写,请手动调整导航属性 public virtual XXX XXX { get; set; }',CHAR(10));  
SET retString=CONCAT(retString,'  
    }  
}',CHAR(10));  
SELECT retString;  
END$$  
  
DELIMITER ;

/*  

call P_GenerateModel('MyDB','ItemContractStock');  

*/  



调用生成,复制到Model.cs中就行了。方便快捷。


不同的项目,可能要根据不同的类名、命名空间等等把固定的部分修改一下,其他的都一样,就是字段、类型和注释的生成。




版权声明:
作者:真爱无限 出处:http://www.pukuimin.top 本文为博主原创文章版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.
« 上一篇下一篇 »

相关文章:

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。