So based on some SQL here and there. I've build a "simple" select that generate class(es) for table(s) or a schema(s)!
What's nice about it, is that it will:
- Keep the column order
- Adding namespaces
- Add the [Table] Attributes on the class.
- Add the [Key] on the primary key(s) (might not be supported by dapper.contrib if 2+ PK)
The function below can be used like so:
select *
from dbo.TableToClass('schema','null or table name') m
where m.TableName not in('unwantedtablename')
order by m.TableSchema asc
, m.TableName asc
, m.ClassOrder asc
, m.ColumnOrder asc;
When you copy paste from SSMS, it might remove the TAB. Here is the code:
CREATE or alter function dbo.TableToClass(
@schema varchar(250)
, @table varchar(250)
)
returns table
as
return
/*
--USE IT LIKE: the order by is necessary on the query
select *
from dbo.TableToClass('schemaName', 'null or table name') m
order by
m.tableSchema asc
, m.tableName asc
, m.ClassOrder asc
, m.columnOrder asc
*/
with typeConversion as(
Select
typeConversion.sqlType
,typeConversion.isNullable
,typeConversion.cSharpType
from
( values
('nvarchar', 'YES', 'string'), ('nvarchar','NO', 'string')
,('varchar', 'YES', 'string'), ('varchar', 'NO', 'string')
,('char', 'YES', 'string'), ('char', 'NO', 'string')
,('datetime', 'YES', 'DateTime?'), ('datetime', 'NO', 'DateTime')
,('datetime2', 'YES', 'DateTime?'), ('datetime2', 'NO', 'DateTime')
,('date', 'YES', 'DateTime?'), ('date', 'NO', 'DateTime')
,('datetimeoffset', 'YES', 'DateTimeOffset?'), ('datetimeoffset', 'NO', 'DateTimeOffset')
,('time', 'YES', 'TimeSpan?'), ('timestamp', 'NO', 'TimeSpan')
,('bigint', 'YES', 'long?'), ('bigint', 'NO', 'long')
,('int', 'YES', 'int?'), ('int', 'NO', 'int')
,('smallint', 'YES', 'Int16?'), ('smallint','NO', 'Int16')
,('decimal', 'YES', 'decimal?'), ('decimal', 'NO', 'decimal')
,('numeric', 'YES', 'decimal?'), ('numeric', 'NO', 'decimal')
,('money', 'YES', 'decimal?'), ('money', 'NO', 'decimal')
,('tinyint', 'YES', 'byte?'), ('tinyint', 'NO', 'byte')
,('varbinary', 'YES', 'byte[]'), ('varbinary', 'NO', 'byte[]?')
,('bit', 'YES', 'bool?'), ('bit', 'NO', 'bool')
,('xml', 'YES', 'string'), ('xml', 'NO', 'string')
) typeConversion(sqlType, isNullable, cSharpType)
), columnInfo as (
select
colInfo.TABLE_SCHEMA
, colInfo.TABLE_NAME
, concat(colInfo.TABLE_SCHEMA, '.', colInfo.TABLE_NAME) FullTableName
, colInfo.COLUMN_NAME
, colInfo.ORDINAL_POSITION
, typeConversion.sqlType
, typeConversion.csharpType
,case
(
Select top 1 pk.CONSTRAINT_TYPE
from INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS columnUsage
join INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS pk
--on pk.CONSTRAINT_TYPE = 'PRIMARY KEY'
on pk.TABLE_SCHEMA = colInfo.TABLE_SCHEMA
and pk.TABLE_NAME = colInfo.TABLE_NAME
and pk.CONSTRAINT_NAME = columnUsage.CONSTRAINT_NAME
where
columnUsage.TABLE_SCHEMA = colInfo.TABLE_SCHEMA
and columnUsage.TABLE_NAME = colInfo.TABLE_NAME
and columnUsage.COLUMN_NAME = colInfo.COLUMN_NAME
)
when 'PRIMARY KEY' then (
case (select COLUMNPROPERTY(OBJECT_ID(concat(colInfo.TABLE_SCHEMA ,'.',colInfo.TABLE_NAME)),colInfo.COLUMN_NAME,'isidentity'))
when 1 then 'PK IDENTITY'
else 'PK'
end
)
when 'FOREIGN KEY' then 'FK'
else 'COL'
end as ColumnType
from INFORMATION_SCHEMA.COLUMNS as colInfo
left join typeConversion on typeConversion.sqlType = colInfo.DATA_TYPE and typeConversion.isNullable = colInfo.IS_NULLABLE
where
/************ SET PARAMETER / CONDITION HERE **************/
( --SCHEMA
'True' = (
case
--when @schema is null then return 'True'
when colInfo.TABLE_SCHEMA = coalesce(@schema, 'dbo') then 'True'
else 'False'
end
)
And -- SET SCHEMA NAME HERE (might be dbo for default)
'True' = ( --Table
case
when @table is null then 'True'
when colInfo.TABLE_NAME = @table then 'True'
else 'False'
end
)
)
), classBuilder2_StartFile as (
select top 1
concat(
'using System;', char(10)
,'using Dapper;', char(10)
,'using Dapper.Contrib;', char(10)
,'using Dapper.Contrib.Extensions;', char(10)
, char(10)
,'namespace MYPROJECTNAMESPACE.',c.TABLE_SCHEMA, '.Models.Db; ', char(10)
) as txt
, 'Using & Namespace' as ClassPart
, 5 as ClassOrder
, c.TABLE_SCHEMA as tableSchema
from columnInfo c
), classBuilder2_StartClass as(
select distinct
concat(
char(10)
, '[Table("',c.FullTableName,'")]', char(10)
, 'public partial class ', c.TABLE_NAME, char(10)
, '{'
) as txt
, 'Class name' as ClassPart
, 17 as ClassOrder
, c.TABLE_NAME as tableName
, c.TABLE_SCHEMA as tableSchema
from columnInfo c
), classBuilder2_Properties as(
select
concat(
case c.ColumnType --Column Attribute for dapper.
when 'PK' then
concat(Char(9),'[ExplicitKey]', char(10)) --Dapper: After insert return 0
when 'PK IDENTITY'then
concat(Char(9),'[Key]', char(10)) -- Dapper: After inser return actual PK
else ''
end
, Char(9), char(9), 'public ', c.csharpType,' ', c.COLUMN_NAME, ' { get; set; }'
) as txt
, ORDINAL_POSITION as columnOrder
, 'Property' as ClassPart
, 30 as ClassOrder
, c.COLUMN_NAME as columnName
, c.TABLE_NAME as tableName
, c.TABLE_SCHEMA as tableSchema
from columnInfo c
), classBuilder2_EndClass as(
select distinct
concat(
char(9), '}'
) as txt
, 'End of C# Class' as ClassPart
, 111 as ClassOrder
, c.TABLE_NAME as tableName
, c.TABLE_SCHEMA as tableSchema
from columnInfo c
), classBuilder2_EndFile as(
select top 1
concat(
char(10),char(10)
) as txt
, 'End of C# Class' as ClassPart
, 120 as ClassOrder
, 'ZZZZZ' as tableName
, 'ZZZZZ' as tableSchema
from columnInfo c
), classBuilder_merge as(
select txt, ClassPart, ClassOrder, 'AAA_SCHEMA' as tableName, tableSchema, 'N/A' as columnName, 0 as columnOrder
from classBuilder2_StartFile
union all
select txt, ClassPart, ClassOrder, tableName, tableSchema, 'N/A' as columnName, 0 as columnOrder
from classBuilder2_StartClass
union all
select txt, ClassPart, ClassOrder, tableName, tableSchema, columnName, columnOrder
from classBuilder2_Properties
union all
select txt, ClassPart, ClassOrder, tableName, tableSchema, 'N/A'as columnNam, 0 as columnOrder
from classBuilder2_EndClass
union all
select txt, ClassPart, ClassOrder, tableName, tableSchema, 'N/A'as columnNam, 0 as columnOrder
from classBuilder2_EndFile
), finalSelect as(
--AFTER SQL Server 2016 (13.x) and later. If before that, remove CROSS APPLY STRING_SPLIT
select top 100 percent
lines.*
, m.tableSchema
, m.tableName
, m.ClassOrder
, m.columnOrder
from classBuilder_merge m
CROSS APPLY STRING_SPLIT(m.txt, char(10)) lines
order by --
m.tableSchema asc
, m.tableName asc
, m.ClassOrder asc
, m.columnOrder asc
)
select * from finalSelect;