源码

github,已更新最新代码

https://github.com/leoparddne/GenEntities/

使用的DB是mysql,所有先nuget一下mysql.data

创建t4模板文件

<#@ assembly name="System.Core"#>
<#@ assembly name="System.Data.Linq"#>
<#@ assembly name="EnvDTE"#>
<#@ assembly name="System.Xml"#>
<#@ assembly name="System.Xml.Linq"#>
<#@ import namespace="System"#>
<#@ import namespace="System.CodeDom"#>
<#@ import namespace="System.CodeDom.Compiler"#>
<#@ import namespace="System.Collections.Generic"#>
<#@ import namespace="System.Data.Linq"#>
<#@ import namespace="System.Data.Linq.Mapping"#>
<#@ import namespace="System.IO"#>
<#@ import namespace="System.Linq"#>
<#@ import namespace="System.Reflection"#>
<#@ import namespace="System.Text"#>
<#@ import namespace="System.Xml.Linq"#>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating"#>
<#+ // Manager class records the various blocks so it can split them up
class Manager {
private class Block {
public String Name;
public int Start, Length;
} private Block currentBlock;
private List<Block> files = new List<Block>();
private Block footer = new Block();
private Block header = new Block();
private ITextTemplatingEngineHost host;
private StringBuilder template;
protected List<String> generatedFileNames = new List<String>(); public static Manager Create(ITextTemplatingEngineHost host, StringBuilder template) {
return (host is IServiceProvider) ? new VSManager(host, template) : new Manager(host, template);
} public void StartNewFile(String name) {
if (name == null)
throw new ArgumentNullException("name");
CurrentBlock = new Block { Name = name };
} public void StartFooter() {
CurrentBlock = footer;
} public void StartHeader() {
CurrentBlock = header;
} public void EndBlock() {
if (CurrentBlock == null)
return;
CurrentBlock.Length = template.Length - CurrentBlock.Start;
if (CurrentBlock != header && CurrentBlock != footer)
files.Add(CurrentBlock);
currentBlock = null;
} public virtual void Process(bool split) {
if (split) {
EndBlock();
String headerText = template.ToString(header.Start, header.Length);
String footerText = template.ToString(footer.Start, footer.Length);
String outputPath = Path.GetDirectoryName(host.TemplateFile);
files.Reverse();
foreach(Block block in files) {
String fileName = Path.Combine(outputPath, block.Name);
String content = headerText + template.ToString(block.Start, block.Length) + footerText;
generatedFileNames.Add(fileName);
CreateFile(fileName, content);
template.Remove(block.Start, block.Length);
}
}
} protected virtual void CreateFile(String fileName, String content) {
if (IsFileContentDifferent(fileName, content))
File.WriteAllText(fileName, content);
} public virtual String GetCustomToolNamespace(String fileName) {
return null;
} public virtual String DefaultProjectNamespace {
get { return null; }
} protected bool IsFileContentDifferent(String fileName, String newContent) {
return !(File.Exists(fileName) && File.ReadAllText(fileName) == newContent);
} private Manager(ITextTemplatingEngineHost host, StringBuilder template) {
this.host = host;
this.template = template;
} private Block CurrentBlock {
get { return currentBlock; }
set {
if (CurrentBlock != null)
EndBlock();
if (value != null)
value.Start = template.Length;
currentBlock = value;
}
} private class VSManager: Manager {
private EnvDTE.ProjectItem templateProjectItem;
private EnvDTE.DTE dte;
private Action<String> checkOutAction;
private Action<IEnumerable<String>> projectSyncAction; public override String DefaultProjectNamespace {
get {
return templateProjectItem.ContainingProject.Properties.Item("DefaultNamespace").Value.ToString();
}
} public override String GetCustomToolNamespace(string fileName) {
return dte.Solution.FindProjectItem(fileName).Properties.Item("CustomToolNamespace").Value.ToString();
} public override void Process(bool split) {
if (templateProjectItem.ProjectItems == null)
return;
base.Process(split);
projectSyncAction.EndInvoke(projectSyncAction.BeginInvoke(generatedFileNames, null, null));
} protected override void CreateFile(String fileName, String content) {
if (IsFileContentDifferent(fileName, content)) {
CheckoutFileIfRequired(fileName);
File.WriteAllText(fileName, content);
}
} internal VSManager(ITextTemplatingEngineHost host, StringBuilder template)
: base(host, template) {
var hostServiceProvider = (IServiceProvider) host;
if (hostServiceProvider == null)
throw new ArgumentNullException("Could not obtain IServiceProvider");
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);
checkOutAction = (String fileName) => dte.SourceControl.CheckOutItem(fileName);
projectSyncAction = (IEnumerable<String> keepFileNames) => ProjectSync(templateProjectItem, keepFileNames);
} private static void ProjectSync(EnvDTE.ProjectItem templateProjectItem, IEnumerable<String> keepFileNames) {
var keepFileNameSet = new HashSet<String>(keepFileNames);
var projectFiles = new Dictionary<String, EnvDTE.ProjectItem>();
var originalFilePrefix = Path.GetFileNameWithoutExtension(templateProjectItem.get_FileNames()) + ".";
foreach(EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems)
projectFiles.Add(projectItem.get_FileNames(), projectItem); // Remove unused items from the project
foreach(var pair in projectFiles)
if (!keepFileNames.Contains(pair.Key) && !(Path.GetFileNameWithoutExtension(pair.Key) + ".").StartsWith(originalFilePrefix))
pair.Value.Delete(); // Add missing files to the project
foreach(String fileName in keepFileNameSet)
if (!projectFiles.ContainsKey(fileName))
templateProjectItem.ProjectItems.AddFromFile(fileName);
} private void CheckoutFileIfRequired(String fileName) {
var sc = dte.SourceControl;
if (sc != null && sc.IsItemUnderSCC(fileName) && !sc.IsItemCheckedOut(fileName))
checkOutAction.EndInvoke(checkOutAction.BeginInvoke(fileName, null, null));
}
}
} #>

将后缀名改为ttinclude,修改名称为Manager.ttinclude

同上创建EntityHelper.tt,将后缀名改为ttinclude,注意第一行的<em id="__mceDel"></em>

<em id="__mceDel"></em>

<#@ assembly name="System.Core"#>
<#@ assembly name="System.Data"#>
<#@ assembly name="MySql.Data" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="MySql.Data.MySqlClient" #>
<#+
public class EntityHelper
{
public static List<Entity> GetEntities(string connectionString, List<string> databases)
{
var list = new List<Entity>();
var conn = new MySqlConnection(connectionString);
try
{
conn.Open();
var dbs = string.Join("','", databases.ToArray());
var cmd = string.Format(@"SELECT `information_schema`.`COLUMNS`.`TABLE_SCHEMA`
,`information_schema`.`COLUMNS`.`TABLE_NAME`
,`information_schema`.`COLUMNS`.`COLUMN_NAME`
,`information_schema`.`COLUMNS`.`DATA_TYPE`
,`information_schema`.`COLUMNS`.`COLUMN_COMMENT`
FROM `information_schema`.`COLUMNS`
WHERE `information_schema`.`COLUMNS`.`TABLE_SCHEMA` IN ('{0}') ", dbs);
using (var reader = MySqlHelper.ExecuteReader(conn, cmd))
{
while (reader.Read())
{
var db = reader["TABLE_SCHEMA"].ToString();
var table = reader["TABLE_NAME"].ToString();
var column = reader["COLUMN_NAME"].ToString();
var type = reader["DATA_TYPE"].ToString();
var comment = reader["COLUMN_COMMENT"].ToString();
var entity = list.FirstOrDefault(x => x.EntityName == table);
if(entity == null)
{
entity = new Entity(table);
entity.Fields.Add(new Field
{
Name = column,
Type = GetCLRType(type),
Comment = comment
}); list.Add(entity);
}
else
{
entity.Fields.Add(new Field
{
Name = column,
Type = GetCLRType(type),
Comment = comment
});
}
}
}
}
finally
{
conn.Close();
} return list;
} public static string GetCLRType(string dbType)
{
switch(dbType)
{
case "tinyint":
case "smallint":
case "mediumint":
case "int":
case "integer":
return "int";
case "double":
return "double";
case "float":
return "float";
case "decimal":
return "decimal";
case "numeric":
case "real":
return "decimal";
case "bit":
return "bool";
case "date":
case "time":
case "year":
case "datetime":
case "timestamp":
return "DateTime";
case "tinyblob":
case "blob":
case "mediumblob":
case "longblog":
case "binary":
case "varbinary":
return "byte[]";
case "char":
case "varchar":
case "tinytext":
case "text":
case "mediumtext":
case "longtext":
return "string";
case "point":
case "linestring":
case "polygon":
case "geometry":
case "multipoint":
case "multilinestring":
case "multipolygon":
case "geometrycollection":
case "enum":
case "set":
default:
return dbType;
}
}
} public class Entity
{
public Entity()
{
this.Fields = new List<Field>();
} public Entity(string name)
: this()
{
this.EntityName = name;
} public string EntityName { get;set; }
public List<Field> Fields { get;set; }
} public class Field
{
public string Name { get;set; }
public string Type { get;set; }
public string Comment { get;set; }
}
#>

任意创建一个.tt文件,修改相关的数据库连接配置部分,保存即可生成实体类

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ include file="Manager.ttinclude" #>
<#@ include file="EntityHelper.ttinclude" #>
<#
// 是否是WCF服务模型
bool serviceModel = false; // 数据库连接
var connectionString = @"Server=172.0.0.1;port=3306;database=testDB;charset=utf8;uid=test;password=test"; // 需要解析的数据库
var database = new List<string> { "testDB" }; // 文件版权信息
var copyright = DateTime.Now.Year + " xxxx Enterprises All Rights Reserved";
var version = Environment.Version;
var author = "auto generated by T4"; var manager = Manager.Create(Host, GenerationEnvironment);
var entities = EntityHelper.GetEntities(connectionString, database); foreach(Entity entity in entities)
{
manager.StartNewFile(entity.EntityName + ".cs");
#>
//-----------------------------------------------------------------------
// <copyright file=" <#= entity.EntityName #>.cs" company="xxxx Enterprises">
// * Copyright (C) <#= copyright #>
// * version : <#= version #>
// * author : <#= author #>
// * FileName: <#= entity.EntityName #>.cs
// * history : Created by T4 <#= DateTime.Now #>
// </copyright>
//-----------------------------------------------------------------------
using System;
<# if(serviceModel)
{
#>
using System.Runtime.Serialization;
<#
}
#> namespace CoreData
{
/// <summary>
/// <#= entity.EntityName #> Entity Model
/// </summary>
<# if(serviceModel)
{
#>
[DataContract]
<#
}
#>
public class <#= entity.EntityName #>
{
<#
for(int i = ; i < entity.Fields.Count; i++)
{
if(i ==){
#> /// <summary>
/// <#= entity.Fields[i].Comment #>
/// </summary>
<# if(serviceModel)
{
#>
[DataMember]
<#
}
#>
public <#= entity.Fields[i].Type #> <#= entity.Fields[i].Name #> { get; set; }
<#
}
else{
#>
/// <summary>
/// <#= entity.Fields[i].Comment #>
/// </summary>
<# if(serviceModel)
{
#>
[DataMember]
<#
}
#>
public <#= entity.Fields[i].Type #> <#= entity.Fields[i].Name #> { get; set; }
<# }
}
#>
}
}
<#
manager.EndBlock();
} manager.Process(true);
#>

使用.net core efcore根据数据库结构自动生成实体类的更多相关文章

  1. mybatis根据数据库表结构自动生成实体类,dao,mapper

    首先, pom需要引入 <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifac ...

  2. Asp.Net Core如何根据数据库自动生成实体类

    通过引用Nuget包添加实体类 运行 Install-Package Microsoft.EntityFrameworkCore.SqlServer 运行 Install-Package Micros ...

  3. 使用T4为数据库自动生成实体类

    T4 (Text Template Transformation Toolkit) 是一个基于模板的代码生成器.使用T4你可以通过写一些ASP.NET-like模板,来生成C#, T-SQL, XML ...

  4. .net core 中简单封装Dapper.Extensions 并使用sqlsuger自动生成实体类

    引言 由公司需要使用dapper  同时支持多数据库 又需要支持实体类 又需要支持sql 还需要支持事务 所以采用了 dapper + dapperExtensions  并配套 生成实体类小工具的方 ...

  5. Mybatis自动生成实体类

    Maven自动生成实体类需要的jar包 一.pom.xml中 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns ...

  6. Springboot mybatis generate 自动生成实体类和Mapper

    https://github.com/JasmineQian/SpringDemo_2019/tree/master/mybatis Springboot让java开发变得方便,Springboot中 ...

  7. Mybatis自动生成实体类、dao接口和mapping映射文件

    由于Mybatis是一种半自动的ORM框架,它的工作主要是配置mapping映射文件,为了减少手动书写映射文件,可以利用mybatis生成器,自动生成实体类.dao接口以及它的映射文件,然后直接拷贝到 ...

  8. Mybatis自动生成实体类和实体映射工具

    Mybatis Mysql生成实体类 用到的Lib包: mybatis-generator-core-1.3.2.jarmysql-connector-java-5.1.30.jar 1. 创建一个文 ...

  9. mybatis根据表逆向自动化生成代码(自动生成实体类、mapper文件、mapper.xml文件)

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

随机推荐

  1. [心得] SQL Server Partition(表分區) 資料分佈探討

    最近在群裡有個朋友問了個問題是這樣的 用户表有一千多万行,主键是用户ID,我做了分区.但经常查询时,其它的表根据用户ID来关联,这样跨区查询,reads非常高.有什么好的处理办法?不分区的话,索引维护 ...

  2. python学习笔记(七)、异常

    在实际开发中,往往不会出现一个系统编写下来,没有出现任何一个bug.为处理这种会出现错误的地方,如除数为零的除法,python提供了非常强大的机制————异常处理机制. 1 异常 python使用异常 ...

  3. git 常用命令,上传,下载,更新线上代码

    git 常用命令以及推荐git新建上传个人博客 $ git clone  //本地如果无远程代码,先做这步,不然就忽略 $ git status //查看本地自己修改了多少文件 $ git add . ...

  4. Python开发爬虫之静态网页抓取篇:爬取“豆瓣电影 Top 250”电影数据

    所谓静态页面是指纯粹的HTML格式的页面,这样的页面在浏览器中展示的内容都在HTML源码中. 目标:爬取豆瓣电影TOP250的所有电影名称,网址为:https://movie.douban.com/t ...

  5. Tips on GORM, Avoid Error about "duplicate column name: id"

    The GORM is an super easy ORM solution for Go language. But many people would get the error about du ...

  6. C#1到C#4使用委托的几种方式

    using System; namespace DelegateDemo { class Program { private delegate int Cacu(string str); static ...

  7. MongoDB 创建索引的语法

    1.为普通字段添加索引,并且为索引命名 db.集合名.createIndex( {"字段名": 1 },{"name":'idx_字段名'}) 说明: (1)索 ...

  8. 启动期间的内存管理之pagging_init初始化分页机制--Linux内存管理(十四)

    1 今日内容(分页机制初始化) 在初始化内存的结点和内存区域之前, 内核先通过pagging_init初始化了内核的分页机制. 在分页机制完成后, 才会开始初始化系统的内存数据结构(包括内存节点数据和 ...

  9. LeetCode算法题-Maximum Depth of N-ary Tree(Java实现)

    这是悦乐书的第261次更新,第274篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第128题(顺位题号是559).给定n-ary树,找到它的最大深度.最大深度是从根节点到 ...

  10. JetBrains 注册码

    C40PF37RR0-eyJsaWNlbnNlSWQiOiJDNDBQRjM3UlIwIiwibGljZW5zZWVOYW1lIjoiemhhbmcgeW9uZyIsImFzc2lnbmVlTmFtZ ...