从数据库表生成类

Posted

技术标签:

【中文标题】从数据库表生成类【英文标题】:Generate class from database table 【发布时间】:2011-08-17 21:46:15 【问题描述】:

如何从 SQL Server 表对象生成类?

我不是在谈论使用一些 ORM。我只需要创建实体(简单类)。比如:

    public class Person 
    
        public string Name  get;set; 
        public string Phone  get;set; 
    

给定一些表格,例如:

+----+-------+----------------+
| ID | Name  |     Phone      |
+----+-------+----------------+
|  1 | Alice | (555) 555-5550 |
|  2 | Bob   | (555) 555-5551 |
|  3 | Cathy | (555) 555-5552 |
+----+-------+----------------+


【问题讨论】:

为什么不让 Entity Framework 为您生成类,而只是不使用与数据库访问有关的类? 我完全同意@John Saunders。过去我自己手动完成,但这太耗时了。在大多数情况下,EF 只是第一次就做对了。如果没有,调整生成的类比自己做所有的时间要少得多。我的时间比编写 ORM 生成器可以为我做的代码更好。我知道我不喜欢生成的代码,但在时间(和成本)节省上的权衡是值得的,至少对我来说是这样。 我认为 EF 确实是最好的解决方案。另一种可能性是 LINQ to sql 类。您只需将其添加到您的项目中并为其提供数据库连接。接下来,您只需选择您需要的表格,它就会为您制作一些课程。 在实践中,EF 并不总是在任何情况下都是最佳解决方案。例如,可能有几个没有经验的开发人员对 edmx 文件进行粗暴的更改,这至少会导致版本冲突……此外,该选项也可能并不总是可用。例如,技术主管可能出于某种原因根本不希望您使用它。 gist.github.com/joey-qc/6710702 【参考方案1】:

将@TableName 设置为您的表的名称。

declare @TableName sysname = 'TableName'
declare @Result varchar(max) = 'public class ' + @TableName + '
'

select @Result = @Result + '
    public ' + ColumnType + NullableSign + ' ' + ColumnName + '  get; set; 
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'double'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'string'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'float'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'long'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by ColumnId

set @Result = @Result  + '
'

print @Result

【讨论】:

对于 Nullable 类型,在 Alex 的 SQL 脚本中将此代码附加在 endColumnType 之间。 + CASE WHEN col.is_nullable=1 AND typ.name NOT IN ('binary', 'varbinary', 'image', 'text', 'ntext', 'varchar', 'nvarchar', 'char', 'nchar') THEN '?' ELSE '' END @AlexAza 你应该把“when 'float' then 'float'”改成“when 'float' then 'double'”,你应该把“when 'real' then 'double'”改成“when 'real' then 'float'”。看来你把这些类型弄糊涂了。相当于 SQL 浮点数的 C# 是双精度数,相当于 SQL 实数的 C# 是浮点数。 不错的答案,但您需要将 print @Result 更改为 print CAST(@Result AS TEXT) 否则它会在大表上被截断。 如何添加数据注释进行验证 - 例如最大字段长度? :) 我已经为output all tables of a database as POCOs/models 派生了一个版本。【参考方案2】:

我无法得到 Alex 在 Sql Server 2008 R2 上工作的答案。因此,我使用相同的基本原则重写了它。它现在允许使用模式,并且已经对列属性映射进行了一些修复(包括将可空日期类型映射到可空 C# 值类型)。这是Sql:

   DECLARE @TableName VARCHAR(MAX) = 'NewsItem' -- Replace 'NewsItem' with your table name
    DECLARE @TableSchema VARCHAR(MAX) = 'Markets' -- Replace 'Markets' with your schema name
    DECLARE @result varchar(max) = ''

    SET @result = @result + 'using System;' + CHAR(13) + CHAR(13) 

    IF (@TableSchema IS NOT NULL) 
    BEGIN
        SET @result = @result + 'namespace ' + @TableSchema  + CHAR(13) + '' + CHAR(13) 
    END

    SET @result = @result + 'public class ' + @TableName + CHAR(13) + '' + CHAR(13) 

    SET @result = @result + '#region Instance Properties' + CHAR(13)  

   SELECT
      @result = @result + CHAR(13)
      + ' public ' + ColumnType + ' ' + ColumnName + '  get; set;  ' + CHAR(13)
    FROM (SELECT
      c.COLUMN_NAME AS ColumnName,
      CASE c.DATA_TYPE
        WHEN 'bigint' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'Int64?'
            ELSE 'Int64'
          END
        WHEN 'binary' THEN 'Byte[]'
        WHEN 'bit' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'bool?'
            ELSE 'bool'
          END
        WHEN 'char' THEN 'string'
        WHEN 'date' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'DateTime?'
            ELSE 'DateTime'
          END
        WHEN 'datetime' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'DateTime?'
            ELSE 'DateTime'
          END
        WHEN 'datetime2' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'DateTime?'
            ELSE 'DateTime'
          END
        WHEN 'datetimeoffset' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'DateTimeOffset?'
            ELSE 'DateTimeOffset'
          END
        WHEN 'decimal' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'decimal?'
            ELSE 'decimal'
          END
        WHEN 'float' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'Single?'
            ELSE 'Single'
          END
        WHEN 'image' THEN 'Byte[]'
        WHEN 'int' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'int?'
            ELSE 'int'
          END
        WHEN 'money' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'decimal?'
            ELSE 'decimal'
          END
        WHEN 'nchar' THEN 'string'
        WHEN 'ntext' THEN 'string'
        WHEN 'numeric' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'decimal?'
            ELSE 'decimal'
          END
        WHEN 'nvarchar' THEN 'string'
        WHEN 'real' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'Double?'
            ELSE 'Double'
          END
        WHEN 'smalldatetime' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'DateTime?'
            ELSE 'DateTime'
          END
        WHEN 'smallint' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'Int16?'
            ELSE 'Int16'
          END
        WHEN 'smallmoney' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'decimal?'
            ELSE 'decimal'
          END
        WHEN 'text' THEN 'string'
        WHEN 'time' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'TimeSpan?'
            ELSE 'TimeSpan'
          END
        WHEN 'timestamp' THEN 'Byte[]'
        WHEN 'tinyint' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'Byte?'
            ELSE 'Byte'
          END
        WHEN 'uniqueidentifier' THEN CASE C.IS_NULLABLE
            WHEN 'YES' THEN 'Guid?'
            ELSE 'Guid'
          END
        WHEN 'varbinary' THEN 'Byte[]'
        WHEN 'varchar' THEN 'string'
        ELSE 'Object'
      END AS ColumnType,
      c.ORDINAL_POSITION
    FROM INFORMATION_SCHEMA.COLUMNS c
    WHERE c.TABLE_NAME = @TableName
    AND ISNULL(@TableSchema, c.TABLE_SCHEMA) = c.TABLE_SCHEMA) t
    ORDER BY t.ORDINAL_POSITION

    SET @result = @result + CHAR(13) + '#endregion Instance Properties' + CHAR(13)  

    SET @result = @result  + '' + CHAR(13)

    IF (@TableSchema IS NOT NULL) 
    BEGIN
        SET @result = @result + CHAR(13) + '' 
    END

    PRINT @result

它产生如下 C#:

using System;

namespace Markets

    public class NewsItem        
        #region Instance Properties

        public Int32 NewsItemID  get; set; 

        public Int32? TextID  get; set; 

        public String Description  get; set; 

        #endregion Instance Properties
    


使用EF、Linq to Sql、甚至Scaffolding可能是个思路;然而,有时像这样的一段代码会派上用场。坦率地说,我不喜欢使用 EF 导航属性,因为它生成的代码进行了 19,200 次单独的数据库调用来填充 1000 行网格。这可以在单个数据库调用中实现。尽管如此,可能只是您的技术架构师不希望您使用 EF 等。所以,你必须恢复到这样的代码......顺便说一句,用 DataAnnotations 等属性装饰每个属性也可能是一个想法,但我严格遵守 POCO。

编辑 TimeStampGuid?

已修复

【讨论】:

+1,这对我也很有效。我将 EF 用于我们的主数据库,但需要从另一个数据库中获取一个存储过程,并且不想为此编写整个 EF 项目,所以这让我可以快速创建一个类来容纳我的存储过程结果集...谢谢 我现在仍在使用它,但我已经包含了字符串长度等的 MVC 属性属性。 为我生成没有属性/列的空类。 @highwingers:您使用的是有效的模式和表名吗?请向我展示您对上述内容的实现。 这是抛光的。我正在使用这个。但感谢 Alex 创建了原始版本。【参考方案3】:

VB版

declare @TableName sysname = 'myTableName'
declare @prop varchar(max)
PRINT 'Public Class ' + @TableName
declare props cursor for
select distinct ' public property ' + ColumnName + ' AS ' + ColumnType AS prop
from ( 
    select  
        replace(col.name, ' ', '_') ColumnName,  column_id, 
        case typ.name  
            when 'bigint' then 'long' 
            when 'binary' then 'byte[]' 
            when 'bit' then 'boolean' 
            when 'char' then 'string' 
            when 'date' then 'DateTime' 
            when 'datetime' then 'DateTime' 
            when 'datetime2' then 'DateTime' 
            when 'datetimeoffset' then 'DateTimeOffset' 
            when 'decimal' then 'decimal' 
            when 'float' then 'float' 
            when 'image' then 'byte[]' 
            when 'int' then 'integer' 
            when 'money' then 'decimal' 
            when 'nchar' then 'char' 
            when 'ntext' then 'string' 
            when 'numeric' then 'decimal' 
            when 'nvarchar' then 'string' 
            when 'real' then 'double' 
            when 'smalldatetime' then 'DateTime' 
            when 'smallint' then 'short' 
            when 'smallmoney' then 'decimal' 
            when 'text' then 'string' 
            when 'time' then 'TimeSpan' 
            when 'timestamp' then 'DateTime' 
            when 'tinyint' then 'byte' 
            when 'uniqueidentifier' then 'Guid' 
            when 'varbinary' then 'byte[]' 
            when 'varchar' then 'string' 
        end ColumnType 
    from sys.columns col join sys.types typ on col.system_type_id = typ.system_type_id 
    where object_id = object_id(@TableName) 
) t 
order by prop
open props
FETCH NEXT FROM props INTO @prop
WHILE @@FETCH_STATUS = 0
BEGIN
    print @prop
    FETCH NEXT FROM props INTO @prop
END
close props
DEALLOCATE props
PRINT 'End Class'

【讨论】:

@highwingers 自 Visual Studio 2010 以来,它们不是必需的 ***.com/a/460032/618186 我必须在顶部添加“使用 MyDatabase”文本才能正常工作。否则它会生成一些无法识别的类属性。 非常好。但是float应该去Doublebyte[]Byte() 做得很好。我什至尝试了一个视图,它就像一个魅力!【参考方案4】:

有点晚了,但我创建了一个网络工具来帮助从 SQL 结果、SQL 表和 SQL SP 创建 C#(或其他)对象。

sql2object.com

这确实可以确保您不必键入所有属性和类型。

如果无法识别类型,将选择默认类型。

【讨论】:

不错但是不能使用表定义脚本作为源 这很棒 :) 它对结果和表格都有效,这很棒。如果您可以修改它以忽略所有 CREATE TABLE 内容,这样我就可以剪切和粘贴所有内容,那就太好了。此外,如果你有机会可以在其中添加一个“Trim()” - 如果开头有一个空行,那么它会失败,然后人们会放弃它。如果您知道将其删除,这很简单 - 但是当您出错时,您会失去人。 还有什么是 SQL 结果集的格式。我只是从文本输出窗口复制和粘贴,它给了我一个包含所有列名的字段:-/ 有什么诀窍? 或者您可以将其开源,让社区按照他们想要的方式构建它。 它不会从“Create Table”脚本创建 C# 类,【参考方案5】:

我想给我的 2 美分

0) 查询优先 https://marketplace.visualstudio.com/items?itemName=bbsimonbb.QueryFirst Query-first 是一个 Visual Studio 扩展,用于在 C# 项目中智能地使用 SQL。使用提供的 .sql 模板来开发您的查询。当您保存文件时,Query-first 运行您的查询,检索架构并生成两个类和一个接口:一个具有 Execute()、ExecuteScalar()、ExecuteNonQuery() 等方法的包装类,其对应的接口和一个 POCO 封装一行结果。

1) Sql2Objects 从查询结果开始创建类(但不是 DAL)

2) https://docs.microsoft.com/en-us/ef/ef6/resources/tools

3) https://visualstudiomagazine.com/articles/2012/12/11/sqlqueryresults-code-generation.aspx

4) http://www.codesmithtools.com/product/generator#features

【讨论】:

【参考方案6】:

要打印出 NULLABLE 属性,请使用这个。 它对 Alex Aza 的 CASE 语句块脚本进行了轻微修改。

declare @TableName sysname = 'TableName'
declare @result varchar(max) = 'public class ' + @TableName + '
'

select @result = @result + '
    public ' + ColumnType + ' ' + ColumnName + '  get; set; 
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end + 
        CASE
            WHEN col.is_nullable=1 AND
                 typ.name NOT IN (
                     'binary', 'varbinary', 'image',
                     'text', 'ntext',
                     'varchar', 'nvarchar', 'char', 'nchar')
            THEN '?'
            ELSE '' END AS [ColumnType]
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id 
    where object_id = object_id(@TableName)
) t
order by column_id

set @result = @result  + '
'

print @result

【讨论】:

【参考方案7】:

是的,如果您使用像 Dapper 这样的简单 ORM,这些都很棒。

如果您使用 .Net,您可以在运行时使用 WriteXmlSchema 方法使用任何 DataSet 生成 XSD 文件。 http://msdn.microsoft.com/en-us/library/xt7k72x8(v=vs.110).aspx

像这样:

using (SqlConnection cnn = new SqlConnection(mConnStr)) 
DataSet Data = new DataSet();
cnn.Open();
string sql = "SELECT * FROM Person";

using (SqlDataAdapter Da = new SqlDataAdapter(sql, cnn))

try

    Da.Fill(Data);
    Da.TableMappings.Add("Table", "Person");
    Data.WriteXmlSchema(@"C:\Person.xsd");

catch (Exception ex)
 MessageBox.Show(ex.Message); 

cnn.Close();

从那里您可以使用 xsd.exe 创建一个可从开发人员命令提示符进行 XML 序列化的类。 http://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx

像这样:

xsd C:\Person.xsd /classes /language:CS

【讨论】:

【参考方案8】:

如果您有权访问 SQL Server 2016,则可以使用 FOR JSON(带有 INCLUDE_NULL_VALUES)选项从 select 语句中获取 JSON 输出。复制输出,然后在 Visual Studio 中粘贴特殊 -> 将 JSON 粘贴为类。

一种预算解决方案,但可能会节省一些时间。

【讨论】:

【参考方案9】:

我尝试使用上述建议,并在此过程中改进了此线程中的解决方案。

假设您使用实现 PropertyChanged 事件的基类(在本例中为 ObservableObject),您将执行类似的操作。有一天我可能会在我的博客上写一篇博文 sqljana.wordpress.com

请用值替换前三个变量:

    --These three things have to be substituted (when called from Powershell, they are replaced before execution)
DECLARE @Schema VARCHAR(MAX) = N'&Schema'
DECLARE @TableName VARCHAR(MAX) = N'&TableName'
DECLARE @Namespace VARCHAR(MAX) = N'&Namespace'

DECLARE @CRLF VARCHAR(2) = CHAR(13) + CHAR(10);
DECLARE @result VARCHAR(max) = ' '

DECLARE @PrivateProp VARCHAR(100) = @CRLF + 
                CHAR(9) + CHAR(9) + 'private <ColumnType> _<ColumnName>;';
DECLARE @PublicProp VARCHAR(255) = @CRLF + 
                CHAR(9) + CHAR(9) + 'public <ColumnType> <ColumnName> '  + @CRLF +
                CHAR(9) + CHAR(9) + ' ' + @CRLF +
                CHAR(9) + CHAR(9) + '   get  return _<ColumnName>;  ' + @CRLF +
                CHAR(9) + CHAR(9) + '   set ' + @CRLF +
                CHAR(9) + CHAR(9) + '    ' + @CRLF +
                CHAR(9) + CHAR(9) + '       _<ColumnName> = value;' + @CRLF +
                CHAR(9) + CHAR(9) + '       base.RaisePropertyChanged();' + @CRLF +
                CHAR(9) + CHAR(9) + '    ' + @CRLF +
                CHAR(9) + CHAR(9) + '' + @CRLF;

DECLARE @RPCProc VARCHAR(MAX) = @CRLF +         
                CHAR(9) + CHAR(9) + 'public event PropertyChangedEventHandler PropertyChanged; ' + @CRLF +
                CHAR(9) + CHAR(9) + 'private void RaisePropertyChanged( ' + @CRLF +
                CHAR(9) + CHAR(9) + '       [CallerMemberName] string caller = "" ) ' + @CRLF +
                CHAR(9) + CHAR(9) + '  ' + @CRLF +
                CHAR(9) + CHAR(9) + '   if (PropertyChanged != null)  ' + @CRLF +
                CHAR(9) + CHAR(9) + '    ' + @CRLF +
                CHAR(9) + CHAR(9) + '       PropertyChanged( this, new PropertyChangedEventArgs( caller ) );  ' + @CRLF +
                CHAR(9) + CHAR(9) + '    ' + @CRLF +
                CHAR(9) + CHAR(9) + '';

DECLARE @PropChanged VARCHAR(200) =  @CRLF +            
                CHAR(9) + CHAR(9) + 'protected override void AfterPropertyChanged(string propertyName) ' + @CRLF +
                CHAR(9) + CHAR(9) + ' ' + @CRLF +
                CHAR(9) + CHAR(9) + '   System.Diagnostics.Debug.WriteLine("' + @TableName + ' property changed: " + propertyName); ' + @CRLF +
                CHAR(9) + CHAR(9) + '';

SET @result = 'using System;' + @CRLF + @CRLF +
                'using MyCompany.Business;' + @CRLF + @CRLF +
                'namespace ' + @Namespace  + @CRLF + '' + @CRLF +
                '   public class ' + @TableName + ' : ObservableObject' + @CRLF + 
                '   ' + @CRLF +
                '   #region Instance Properties' + @CRLF 

SELECT @result = @result
                 + 
                REPLACE(
                            REPLACE(@PrivateProp
                            , '<ColumnName>', ColumnName)
                        , '<ColumnType>', ColumnType)
                +                           
                REPLACE(
                            REPLACE(@PublicProp
                            , '<ColumnName>', ColumnName)
                        , '<ColumnType>', ColumnType)                   
FROM
(
    SELECT  c.COLUMN_NAME   AS ColumnName 
        , CASE c.DATA_TYPE   
            WHEN 'bigint' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Int64?' ELSE 'Int64' END
            WHEN 'binary' THEN 'Byte[]'
            WHEN 'bit' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Boolean?' ELSE 'Boolean' END            
            WHEN 'char' THEN 'String'
            WHEN 'date' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                        
            WHEN 'datetime' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                        
            WHEN 'datetime2' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                        
            WHEN 'datetimeoffset' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTimeOffset?' ELSE 'DateTimeOffset' END                                    
            WHEN 'decimal' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                    
            WHEN 'float' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Single?' ELSE 'Single' END                                    
            WHEN 'image' THEN 'Byte[]'
            WHEN 'int' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Int32?' ELSE 'Int32' END
            WHEN 'money' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                                
            WHEN 'nchar' THEN 'String'
            WHEN 'ntext' THEN 'String'
            WHEN 'numeric' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                                            
            WHEN 'nvarchar' THEN 'String'
            WHEN 'real' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Double?' ELSE 'Double' END                                                                        
            WHEN 'smalldatetime' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                                    
            WHEN 'smallint' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Int16?' ELSE 'Int16'END            
            WHEN 'smallmoney' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                                                        
            WHEN 'text' THEN 'String'
            WHEN 'time' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'TimeSpan?' ELSE 'TimeSpan' END                                                                                    
            WHEN 'timestamp' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                                    
            WHEN 'tinyint' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Byte?' ELSE 'Byte' END                                                
            WHEN 'uniqueidentifier' THEN 'Guid'
            WHEN 'varbinary' THEN 'Byte[]'
            WHEN 'varchar' THEN 'String'
            ELSE 'Object'
        END AS ColumnType
        , c.ORDINAL_POSITION 
FROM    INFORMATION_SCHEMA.COLUMNS c
WHERE   c.TABLE_NAME = @TableName 
    AND ISNULL(@Schema, c.TABLE_SCHEMA) = c.TABLE_SCHEMA  
) t
ORDER BY t.ORDINAL_POSITION

SELECT @result = @result + @CRLF + 
                CHAR(9) + '#endregion Instance Properties' + @CRLF +
                --CHAR(9) + @RPCProc + @CRLF +
                CHAR(9) + @PropChanged + @CRLF +
                CHAR(9) + '' + @CRLF +
                @CRLF + '' 
--SELECT @result
PRINT @result

基类基于 Josh Smith 在此处的文章 来自http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/

我确实将类重命名为 ObservableObject,并且还利用了 c# 5 的 CallerMemberName 属性特性

//From http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
//
//Jana's change: Used c# 5 feature to bypass passing in the property name using [CallerMemberName] 
//  protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace MyCompany.Business


    /// <summary>
    /// Implements the INotifyPropertyChanged interface and 
    /// exposes a RaisePropertyChanged method for derived 
    /// classes to raise the PropertyChange event.  The event 
    /// arguments created by this class are cached to prevent 
    /// managed heap fragmentation.
    /// </summary>
    [Serializable]
    public abstract class ObservableObject : INotifyPropertyChanged
    
        #region Data

        private static readonly Dictionary<string, PropertyChangedEventArgs> eventArgCache;
        private const string ERROR_MSG = "0 is not a public property of 1";

        #endregion // Data

        #region Constructors

        static ObservableObject()
        
            eventArgCache = new Dictionary<string, PropertyChangedEventArgs>();
        

        protected ObservableObject()
        
        

        #endregion // Constructors

        #region Public Members

        /// <summary>
        /// Raised when a public property of this object is set.
        /// </summary>
        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Returns an instance of PropertyChangedEventArgs for 
        /// the specified property name.
        /// </summary>
        /// <param name="propertyName">
        /// The name of the property to create event args for.
        /// </param>        
        public static PropertyChangedEventArgs
            GetPropertyChangedEventArgs(string propertyName)
        
            if (String.IsNullOrEmpty(propertyName))
                throw new ArgumentException(
                    "propertyName cannot be null or empty.");

            PropertyChangedEventArgs args;

            // Get the event args from the cache, creating them
            // and adding to the cache if necessary.
            lock (typeof(ObservableObject))
            
                bool isCached = eventArgCache.ContainsKey(propertyName);
                if (!isCached)
                
                    eventArgCache.Add(
                        propertyName,
                        new PropertyChangedEventArgs(propertyName));
                

                args = eventArgCache[propertyName];
            

            return args;
        

        #endregion // Public Members

        #region Protected Members

        /// <summary>
        /// Derived classes can override this method to
        /// execute logic after a property is set. The 
        /// base implementation does nothing.
        /// </summary>
        /// <param name="propertyName">
        /// The property which was changed.
        /// </param>
        protected virtual void AfterPropertyChanged(string propertyName)
        
        

        /// <summary>
        /// Attempts to raise the PropertyChanged event, and 
        /// invokes the virtual AfterPropertyChanged method, 
        /// regardless of whether the event was raised or not.
        /// </summary>
        /// <param name="propertyName">
        /// The property which was changed.
        /// </param>
        protected void RaisePropertyChanged([CallerMemberName] string propertyName = "")
        
            this.VerifyProperty(propertyName);

            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            
                // Get the cached event args.
                PropertyChangedEventArgs args =
                    GetPropertyChangedEventArgs(propertyName);

                // Raise the PropertyChanged event.
                handler(this, args);
            

            this.AfterPropertyChanged(propertyName);
        

        #endregion // Protected Members

        #region Private Helpers

        [Conditional("DEBUG")]
        private void VerifyProperty(string propertyName)
        
            Type type = this.GetType();

            // Look for a public property with the specified name.
            PropertyInfo propInfo = type.GetProperty(propertyName);

            if (propInfo == null)
            
                // The property could not be found,
                // so alert the developer of the problem.

                string msg = string.Format(
                    ERROR_MSG,
                    propertyName,
                    type.FullName);

                Debug.Fail(msg);
            
        

        #endregion // Private Helpers
    

这是你们会更喜欢的部分。我构建了一个 Powershell 脚本来为 SQL 数据库中的所有表生成。它基于一个名为 Chad Miller 的 Invoke-SQLCmd2 cmdlet 的 Powershell 大师,可以从这里下载: http://gallery.technet.microsoft.com/ScriptCenter/7985b7ef-ed89-4dfd-b02a-433cc4e30894/

拥有该 cmdlet 后,为所有表生成的 Powershell 脚本就变得很简单(用您的特定值替换变量)。

. C:\MyScripts\Invoke-Sqlcmd2.ps1

$serverInstance = "mysqlInstance"
$databaseName = "MyDb"
$generatorSQLFile = "C:\MyScripts\ModelGen.sql" 
$tableListSQL = "SELECT name FROM $databaseName.sys.tables"
$outputFolder = "C:\MyScripts\Output\"
$namespace = "MyCompany.Business"

$placeHolderSchema = "&Schema"
$placeHolderTableName = "&TableName"
$placeHolderNamespace = "&Namespace"

#Get the list of tables in the database to generate c# models for
$tables = Invoke-Sqlcmd2 -ServerInstance $serverInstance -Database $databaseName -Query $tableListSQL -As DataRow -Verbose

foreach ($table in $tables)

    $table1 = $table[0]
    $outputFile = "$outputFolder\$table1.cs"


    #Replace variables with values (returns an array that we convert to a string to use as query)
    $generatorSQLFileWSubstitutions = (Get-Content $generatorSQLFile).
                                            Replace($placeHolderSchema,"dbo").
                                            Replace($placeHolderTableName, $table1).
                                            Replace($placeHolderNamespace, $namespace) | Out-String

    "Ouputing for $table1 to $outputFile"

    #The command generates .cs file content for model using "PRINT" statements which then gets written to verbose output (stream 4)
    # ...capture the verbose output and redirect to a file
    (Invoke-Sqlcmd2 -ServerInstance $serverInstance -Database $databaseName -Query $generatorSQLFileWSubstitutions -Verbose) 4> $outputFile


【讨论】:

自从我问这个问题已经 3 年多了,我现在不使用 sql 数据库(大数据、mongodb 等)。但我肯定会很快对此进行测试,您在阐述这个答案并为社区做出贡献时度过了愉快的时光。非常感谢! 我已经使用 *** 很长时间了,但现在才开始贡献。所以,你可以说我开始学习 S.O.礼仪也是。当我在寻找这样的解决方案时,我偶然发现了这个线程并添加了我的扩展解决方案,以便未来的用户可以从中受益。感谢您的评论。 谢谢。是否可以在 tsql 脚本中完成所有这些操作 - 而不是使用 powershell?【参考方案10】:

使用模板创建自定义代码的过程

create PROCEDURE [dbo].[createCode]
(   
   @TableName sysname = '',
   @befor varchar(max)='public class  @TableName  
',
   @templet varchar(max)=' 
     public @ColumnType @ColumnName    get; set;   // @ColumnDesc  ',
   @after varchar(max)='
'

)
AS
BEGIN 


declare @result varchar(max)

set @befor =replace(@befor,'@TableName',@TableName)

set @result=@befor

select @result = @result 
+ replace(replace(replace(replace(replace(@templet,'@ColumnType',ColumnType) ,'@ColumnName',ColumnName) ,'@ColumnDesc',ColumnDesc),'@ISPK',ISPK),'@max_length',max_length)

from  
(
    select 
    column_id,
    replace(col.name, ' ', '_') ColumnName,
    typ.name as sqltype,
    typ.max_length,
    is_identity,
    pkk.ISPK, 
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'String'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'String'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'String'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        END + CASE WHEN col.is_nullable=1 AND typ.name NOT IN ('binary', 'varbinary', 'image', 'text', 'ntext', 'varchar', 'nvarchar', 'char', 'nchar') THEN '?' ELSE '' END ColumnType,
      isnull(colDesc.colDesc,'') AS ColumnDesc 
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
            left join
            (
                SELECT c.name  AS 'ColumnName', CASE WHEN dd.pk IS NULL THEN 'false' ELSE 'true' END ISPK           
                FROM        sys.columns c
                    JOIN    sys.tables  t   ON c.object_id = t.object_id    
                    LEFT JOIN (SELECT   K.COLUMN_NAME , C.CONSTRAINT_TYPE as pk  
                        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K 
                            LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS C
                        ON K.TABLE_NAME = C.TABLE_NAME
                            AND K.CONSTRAINT_NAME = C.CONSTRAINT_NAME
                            AND K.CONSTRAINT_CATALOG = C.CONSTRAINT_CATALOG
                            AND K.CONSTRAINT_SCHEMA = C.CONSTRAINT_SCHEMA            
                        WHERE K.TABLE_NAME = @TableName) as dd
                     ON dd.COLUMN_NAME = c.name
                 WHERE       t.name = @TableName       
            ) pkk  on ColumnName=col.name

    OUTER APPLY (
    SELECT TOP 1 CAST(value AS NVARCHAR(max)) AS colDesc
    FROM
       sys.extended_properties
    WHERE
       major_id = col.object_id
       AND
       minor_id = COLUMNPROPERTY(major_id, col.name, 'ColumnId')
    ) colDesc      
    where object_id = object_id(@TableName)

    ) t

    set @result=@result+@after

    select @result
    --print @result

END

现在创建自定义代码

例如 c# 类

exec [createCode] @TableName='book',@templet =' 
     public @ColumnType @ColumnName    get; set;   // @ColumnDesc  '

输出是

public class  book  
 
     public long ID    get; set;   //    
     public String Title    get; set;   // Book Title  

对于 LINQ

exec [createCode] @TableName='book'
, @befor  ='[System.Data.Linq.Mapping.Table(Name = "@TableName")]
public class @TableName
',

   @templet  =' 
     [System.Data.Linq.Mapping.Column(Name = "@ColumnName", IsPrimaryKey = @ISPK)]
     public @ColumnType @ColumnName    get; set;   // @ColumnDesc  
     ' ,

   @after  ='
'

输出是

[System.Data.Linq.Mapping.Table(Name = "book")]
public class book
 
     [System.Data.Linq.Mapping.Column(Name = "ID", IsPrimaryKey = true)]
     public long ID    get; set;   //   

     [System.Data.Linq.Mapping.Column(Name = "Title", IsPrimaryKey = false)]
     public String Title    get; set;   // Book Title  


对于java类

exec [createCode] @TableName='book',@templet =' 
     public @ColumnType @ColumnName ; // @ColumnDesc  
     public @ColumnType get@ColumnName()
     
        return this.@ColumnName;
     
     public void set@ColumnName(@ColumnType @ColumnName)
     
        this.@ColumnName=@ColumnName;
     

     '

输出是

public class  book  
 
     public long ID ; //   
     public long getID()
     
        return this.ID;
     
     public void setID(long ID)
     
        this.ID=ID;
     


     public String Title ; // Book Title  
     public String getTitle()
     
        return this.Title;
     
     public void setTitle(String Title)
     
        this.Title=Title;
      

适用于安卓 SugarOrm 模型

exec [createCode] @TableName='book'
, @befor  ='@Table(name = "@TableName")
public class @TableName
',
   @templet  =' 
     @Column(name = "@ColumnName")
     public @ColumnType @ColumnName ;// @ColumnDesc  
     ' ,
   @after  ='
'

输出是

@Table(name = "book")
public class book
 
     @Column(name = "ID")
     public long ID ;//   

     @Column(name = "Title")
     public String Title ;// Book Title  


【讨论】:

【参考方案11】:

Visual Studio 杂志发表了这篇文章:

Generating .NET POCO Classes for SQL Query Results

它有一个可下载的项目,您可以构建它,给它您的 SQL 信息,它会为您制作课程。

现在,如果该工具刚刚为 SELECT、INSERT 和 UPDATE 创建了 SQL 命令......

【讨论】:

【参考方案12】:

要打印出带有注释(摘要)的 NULLABLE 属性,请使用它。 这是对第一个答案的轻微修改

declare @TableName sysname = 'TableName'
declare @result varchar(max) = 'public class ' + @TableName + '
'
select @result = @result 
+ CASE WHEN ColumnDesc IS NOT NULL THEN '
    /// <summary>
    /// ' + ColumnDesc + '
    /// </summary>' ELSE '' END
+ '
    public ' + ColumnType + ' ' + ColumnName + '  get; set; '
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'String'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'String'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'String'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        END + CASE WHEN col.is_nullable=1 AND typ.name NOT IN ('binary', 'varbinary', 'image', 'text', 'ntext', 'varchar', 'nvarchar', 'char', 'nchar') THEN '?' ELSE '' END ColumnType,
        colDesc.colDesc AS ColumnDesc
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    OUTER APPLY (
    SELECT TOP 1 CAST(value AS NVARCHAR(max)) AS colDesc
    FROM
       sys.extended_properties
    WHERE
       major_id = col.object_id
       AND
       minor_id = COLUMNPROPERTY(major_id, col.name, 'ColumnId')
    ) colDesc            
    where object_id = object_id(@TableName)
) t
order by column_id

set @result = @result  + '
'

print @result

【讨论】:

【参考方案13】:

只是想我会为任何感兴趣的人添加我自己的最佳答案变体。 主要特点是:

它将自动为整个架构中的所有表生成类。只需指定架构名称。

它将 System.Data.Linq.Mapping 属性添加到类和每个属性。对使用 Linq to SQL 的任何人都有用。

declare @TableName sysname
declare @Result varchar(max)
declare @schema varchar(20) = 'dbo'
DECLARE @Cursor CURSOR

SET @Cursor = CURSOR FAST_FORWARD FOR
SELECT DISTINCT tablename = rc1.TABLE_NAME
FROM INFORMATION_SCHEMA.Tables rc1
where rc1.TABLE_SCHEMA = @schema

OPEN @Cursor FETCH NEXT FROM @Cursor INTO @TableName

WHILE (@@FETCH_STATUS = 0)
BEGIN
set @Result = '[Table(Name = "' + @schema + '.' + @TableName + '")]
public class ' + Replace(@TableName, '$', '_') + '
'

select @Result = @Result + '
    [Column' + PriKey +']
    public ' + ColumnType + NullableSign + ' ' + ColumnName + '  get; set; 
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        col.column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'double'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'string'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'float'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'long'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign,
        case
            when pk.CONSTRAINT_NAME is not null and ic.column_id is not null then '(IsPrimaryKey = true, IsDbGenerated = true)'
            when pk.CONSTRAINT_NAME is not null then '(IsPrimaryKey = true)'
            when ic.column_id is not null then '(IsDbGenerated = true)'
            else ''
        end PriKey
    from sys.columns col
    join sys.types typ on col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    left outer join sys.identity_columns ic on ic.column_id = col.column_id and col.object_id = ic.object_id
    left outer join (
        SELECT  K.TABLE_NAME ,
            K.COLUMN_NAME ,
            K.CONSTRAINT_NAME
        FROM    INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS C
                JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K ON C.TABLE_NAME = K.TABLE_NAME
                                                                 AND C.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
                                                                 AND C.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
                                                                 AND C.CONSTRAINT_NAME = K.CONSTRAINT_NAME
        where C.CONSTRAINT_TYPE = 'PRIMARY KEY'
    ) pk on pk.COLUMN_NAME = col.name and pk.TABLE_NAME = @TableName
    where col.object_id = object_id(@schema + '.' + @TableName)
) t
order by ColumnId

set @Result = @Result  + '


'

print @Result

FETCH NEXT FROM @Cursor INTO @TableName
end

CLOSE @Cursor DEALLOCATE @Cursor
GO

【讨论】:

感谢整个架构上的即用型光标,您为我节省了很多时间!【参考方案14】:

商业,但 CodeSmith Generator 可以做到这一点:http://www.codesmithtools.com/product/generator

【讨论】:

【参考方案15】:

我对你想要从中得到什么感到困惑,但这里是设计你想要设计的东西时的一般选项。

    在您的 Visual Studio 版本中使用内置 ORM。 自己编写一个,类似于您的代码示例。像往常一样,如果您不确定如何使用,教程是您最好的朋友。 使用替代 ORM,例如 NHibernate。

【讨论】:

【参考方案16】:

感谢 Alex 的解决方案和 Guilherme 要求我为 MySQL 制作这个以生成 C# 类

set @schema := 'schema_name';
set @table := 'table_name';
SET group_concat_max_len = 2048;
SELECT 
    concat('public class ', @table, '\n\n', GROUP_CONCAT(a.property_ SEPARATOR '\n'), '\n') class_
FROM 
    (select
        CONCAT(
        '\tpublic ',
        case 
            when DATA_TYPE = 'bigint' then 'long'
            when DATA_TYPE = 'BINARY' then 'byte[]'
            when DATA_TYPE = 'bit' then 'bool'
            when DATA_TYPE = 'char' then 'string'
            when DATA_TYPE = 'date' then 'DateTime'
            when DATA_TYPE = 'datetime' then 'DateTime'
            when DATA_TYPE = 'datetime2' then 'DateTime'
            when DATA_TYPE = 'datetimeoffset' then 'DateTimeOffset'
            when DATA_TYPE = 'decimal' then 'decimal'
            when DATA_TYPE = 'double' then 'double'
            when DATA_TYPE = 'float' then 'float'
            when DATA_TYPE = 'image' then 'byte[]'
            when DATA_TYPE = 'int' then 'int'
            when DATA_TYPE = 'money' then 'decimal'
            when DATA_TYPE = 'nchar' then 'char'
            when DATA_TYPE = 'ntext' then 'string'
            when DATA_TYPE = 'numeric' then 'decimal'
            when DATA_TYPE = 'nvarchar' then 'string'
            when DATA_TYPE = 'real' then 'double'
            when DATA_TYPE = 'smalldatetime' then 'DateTime'
            when DATA_TYPE = 'smallint' then 'short'
            when DATA_TYPE = 'smallmoney' then 'decimal'
            when DATA_TYPE = 'text' then 'string'
            when DATA_TYPE = 'time' then 'TimeSpan'
            when DATA_TYPE = 'timestamp' then 'DateTime'
            when DATA_TYPE = 'tinyint' then 'byte'
            when DATA_TYPE = 'uniqueidentifier' then 'Guid'
            when DATA_TYPE = 'varbinary' then 'byte[]'
            when DATA_TYPE = 'varchar' then 'string'
            else '_UNKNOWN_'
        end, ' ', 
        COLUMN_NAME, ' get; set;') as property_
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE table_name = @table AND table_schema = @schema) a
;
Thanks Alex and Guilherme!

【讨论】:

谢谢!我只是在找这个!【参考方案17】:

Grab QueryFirst,Visual Studio 扩展,可从 SQL 查询生成包装类。你不仅得到...

public class MyClass
    public string MyPropget;set;
    public int MyNumberPropget;set;
    ...

作为奖励,它会加入......

public class MyQuery
    public static IEnumerable<MyClass>Execute()
    public static MyClass GetOne()
    ...

您确定要将类直接基于您的表吗?表是属于数据库的静态、规范化数据存储概念。类是动态的、流动的、一次性的、特定于上下文的,也许是非规范化的。为什么不为操作所需的数据编写真正的查询,并让 QueryFirst 从中生成类。

【讨论】:

【参考方案18】:

这篇文章救了我好几次。我只想加两分钱。 对于那些不喜欢使用 ORM 而是编写自己的 DAL 类的人来说,当您在一个表中有 20 列,以及 40 个具有各自 CRUD 操作的不同表时,这既痛苦又浪费时间。我重复了上面的代码,用于根据表实体和属性生成 CRUD 方法。

 declare @TableName sysname = 'Tablename'
declare @Result varchar(max) = 'public class ' + @TableName + '
'

select @Result = @Result + '
    public ' + ColumnType + NullableSign + ' ' + ColumnName + '  get; set; 
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by ColumnId

set @Result = @Result  + '
'

print @Result

declare @InitDataAccess varchar(max) = 'public class '+ @TableName +'DataAccess 
 '

declare @ListStatement varchar(max) ='public List<'+@TableName+'> Get'+@TableName+'List()

 String conn = ConfigurationManager.ConnectionStrings["ConnectionNameInWeb.config"].ConnectionString;
 var itemList = new List<'+@TableName+'>();
          try
            
                using (var sqlCon = new SqlConnection(conn))
                
                    sqlCon.Open();
                    var cmd = new SqlCommand
                    
                        Connection = sqlCon,
                        CommandType = CommandType.StoredProcedure,
                        CommandText = "StoredProcedureSelectAll"
                    ;
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    
                      var item = new '+@TableName+'();
' 
select @ListStatement = @ListStatement + '
item.'+ ColumnName + '= ('+ ColumnType + NullableSign  +')reader["'+ColumnName+'"];
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by ColumnId

select @ListStatement = @ListStatement +'
                        itemList.Add(item);
                    

                
            
            catch (Exception ex)
            
                throw new Exception(ex.Message);
            
            return itemList;
        '

declare @GetIndividual varchar(max) =  
'public '+@TableName+' Get'+@TableName+'()

 String conn = ConfigurationManager.ConnectionStrings["ConnectionNameInWeb.config"].ConnectionString;
 var item = new '+@TableName+'();
          try
            
                using (var sqlCon = new SqlConnection(conn))
                
                    sqlCon.Open();
                    var cmd = new SqlCommand
                    
                        Connection = sqlCon,
                        CommandType = CommandType.StoredProcedure,
                        CommandText = "StoredProcedureSelectIndividual"
                    ;
                     cmd.Parameters.AddWithValue("@ItemCriteria", item.id);
                    SqlDataReader reader = cmd.ExecuteReader();
                    if (reader.Read())
                    ' 
select @GetIndividual = @GetIndividual + '
item.'+ ColumnName + '= ('+ ColumnType + NullableSign  +')reader["'+ColumnName+'"];
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by ColumnId

select @GetIndividual = @GetIndividual +'

                    

                
            
            catch (Exception ex)
            
                throw new Exception(ex.Message);
            
            return item;
        '



declare @InsertStatement varchar(max) = 'public void  Insert'+@TableName+'('+@TableName+' item)

 String conn = ConfigurationManager.ConnectionStrings["ConnectionNameInWeb.config"].ConnectionString;

          try
            
                using (var sqlCon = new SqlConnection(conn))
                
                    sqlCon.Open();
                    var cmd = new SqlCommand
                    
                        Connection = sqlCon,
                        CommandType = CommandType.StoredProcedure,
                        CommandText = "StoredProcedureInsert"
                    ;

                    ' 
select @InsertStatement = @InsertStatement + '
 cmd.Parameters.AddWithValue("@'+ColumnName+'", item.'+ColumnName+');
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by ColumnId

select @InsertStatement = @InsertStatement +'

                    cmd.ExecuteNonQuery();

                
            
            catch (Exception ex)
            
                throw new Exception(ex.Message);
            

        '

declare @UpdateStatement varchar(max) = 'public void  Update'+@TableName+'('+@TableName+' item)

 String conn = ConfigurationManager.ConnectionStrings["ConnectionNameInWeb.config"].ConnectionString;

          try
            
                using (var sqlCon = new SqlConnection(conn))
                
                    sqlCon.Open();
                    var cmd = new SqlCommand
                    
                        Connection = sqlCon,
                        CommandType = CommandType.StoredProcedure,
                        CommandText = "StoredProcedureUpdate"
                    ;
                    cmd.Parameters.AddWithValue("@UpdateCriteria", item.Id);
                    ' 
select @UpdateStatement = @UpdateStatement + '
 cmd.Parameters.AddWithValue("@'+ColumnName+'", item.'+ColumnName+');
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by ColumnId

select @UpdateStatement = @UpdateStatement +'

                    cmd.ExecuteNonQuery();

                
            
            catch (Exception ex)
            
                throw new Exception(ex.Message);
            

        '

declare @EndDataAccess varchar(max)  = '
'
 print @InitDataAccess
 print @GetIndividual
print @InsertStatement
print @UpdateStatement
print @ListStatement
print @EndDataAccess

当然它不是防弹代码,并且可以改进。只是想为这个出色的解决方案做出贡献

【讨论】:

【参考方案19】:

根据上面的回复稍作修改:

declare @TableName sysname = 'HistoricCommand'

declare @Result varchar(max) = '[System.Data.Linq.Mapping.Table(Name = "' + @TableName + '")]
public class Dbo' + @TableName + '
'

select @Result = @Result + '
    [System.Data.Linq.Mapping.Column(Name = "' + t.ColumnName + '", IsPrimaryKey = ' + pkk.ISPK + ')]
    public ' + ColumnType + NullableSign + ' ' + t.ColumnName + '  get; set; 
'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id ColumnId,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'string'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType,
        case 
            when col.is_nullable = 1 and typ.name in ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') 
            then '?' 
            else '' 
        end NullableSign
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id         
    where object_id = object_id(@TableName) 
) t, 
(
                SELECT c.name  AS 'ColumnName', CASE WHEN dd.pk IS NULL THEN 'false' ELSE 'true' END ISPK           
                FROM        sys.columns c
                    JOIN    sys.tables  t   ON c.object_id = t.object_id    
                    LEFT JOIN (SELECT   K.COLUMN_NAME , C.CONSTRAINT_TYPE as pk  
                        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K 
                            LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS C
                        ON K.TABLE_NAME = C.TABLE_NAME
                            AND K.CONSTRAINT_NAME = C.CONSTRAINT_NAME
                            AND K.CONSTRAINT_CATALOG = C.CONSTRAINT_CATALOG
                            AND K.CONSTRAINT_SCHEMA = C.CONSTRAINT_SCHEMA            
                        WHERE K.TABLE_NAME = @TableName) as dd
                     ON dd.COLUMN_NAME = c.name
                 WHERE       t.name = @TableName            
            ) pkk
where pkk.ColumnName = t.ColumnName
order by ColumnId

set @Result = @Result  + '
'

print @Result

这使得 C# 声明中的完整 LINQ 需要输出

[System.Data.Linq.Mapping.Table(Name = "HistoricCommand")]
public class DboHistoricCommand

    [System.Data.Linq.Mapping.Column(Name = "HistoricCommandId", IsPrimaryKey = true)]
    public int HistoricCommandId  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "PHCloudSoftwareInstanceId", IsPrimaryKey = true)]
    public int PHCloudSoftwareInstanceId  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "CommandType", IsPrimaryKey = false)]
    public int CommandType  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "InitiatedDateTime", IsPrimaryKey = false)]
    public DateTime InitiatedDateTime  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "CompletedDateTime", IsPrimaryKey = false)]
    public DateTime CompletedDateTime  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "WasSuccessful", IsPrimaryKey = false)]
    public bool WasSuccessful  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "Message", IsPrimaryKey = false)]
    public string Message  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "ResponseData", IsPrimaryKey = false)]
    public string ResponseData  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "Message_orig", IsPrimaryKey = false)]
    public string Message_orig  get; set; 

    [System.Data.Linq.Mapping.Column(Name = "Message_XX", IsPrimaryKey = false)]
    public string Message_XX  get; set; 


【讨论】:

【参考方案20】:

我在这里将几个基于 SQL 的答案(主要是 Alex Aza 的根答案)中的想法打包到 klassify 中,这是一个控制台应用程序,可以一次为指定数据库生成所有类: p>


例如,给定一个表Users,如下所示:

+----+------------------+-----------+---------------------+
| Id |       Name       | Username  |        Email        |
+----+------------------+-----------+---------------------+
|  1 | Leanne Graham    | Bret      | Sincere@april.biz   |
|  2 | Ervin Howell     | Antonette | Shanna@melissa.tv   |
|  3 | Clementine Bauch | Samantha  | Nathan@yesenia.net  |
+----+------------------+-----------+---------------------+

klassify 将生成一个名为Users.cs 的文件,如下所示:

    public class User 
    
        public int Id get; set; 
        public string Name  get;set; 
        public string Username  get; set; 
        public string Email  get; set; 
    

它将为每个表输出一个文件。丢弃你不使用的东西。

用法

 --out, -o:
        output directory     << defaults to the current directory >>
 --user, -u:
        sql server user id   << required >>
 --password, -p:
        sql server password  << required >>
 --server, -s:
        sql server           << defaults to localhost >>
 --database, -d:
        sql database         << required >>
 --timeout, -t:
        connection timeout   << defaults to 30 >>
 --help, -h:
        show help

【讨论】:

【参考方案21】:

Oracle DB 的另一种解决方案 -> C#

单一查询 无函数无过程 多表

添加数据注释

[键] [必填] [表格] [字符串长度] [列] 可以为空

查询

https://gist.github.com/omansak/f19eefffd2d639ac72a1f4b506d8471a

输出

[Table("AGENTS")]
public class Agents

    [Key]
    [Required]
    [Column("INT_ID", TypeName = "NUMBER(10,0)", Order = 1)]
    public long IntId  get; set; 
    [Key]
    [Required]
    [StringLength(15)]
    [Column("REFERENCE_CODE", TypeName = "VARCHAR2(15)", Order = 2)]
    public string ReferenceCode  get; set; 
    [Required]
    [Column("PARENT_INT_ID", TypeName = "NUMBER(10,0)", Order = 3)]
    public long ParentIntId  get; set; 
    [Required]
    [StringLength(200)]
    [Column("TITLE", TypeName = "VARCHAR2(200)", Order = 4)]
    public string Title  get; set; 
    [Required]
    [Column("START_DATE", TypeName = "DATE", Order = 5)]
    public DateTime StartDate  get; set; 
    [Required]
    [Column("END_DATE", TypeName = "DATE", Order = 6)]
    public DateTime EndDate  get; set; 
    [Required]
    [StringLength(1)]
    [Column("AGENT_TYPE", TypeName = "VARCHAR2(1)", Order = 7)]
    public string AgentType  get; set; 
    [Required]
    [Column("CREATE_DATE", TypeName = "DATE", Order = 8)]
    public DateTime CreateDate  get; set; 
    [Required]
    [StringLength(32)]
    [Column("CREATE_USER", TypeName = "VARCHAR2(32)", Order = 9)]
    public string CreateUser  get; set; 
    [StringLength(200)]
    [Column("RESPONSIBLE_CONTACT", TypeName = "VARCHAR2(200)", Order = 10)]
    public string ResponsibleContact  get; set; 
    [StringLength(100)]
    [Column("RESPONSIBLE_TITLE", TypeName = "VARCHAR2(100)", Order = 11)]
    public string ResponsibleTitle  get; set; 
    [StringLength(100)]
    [Column("AGENCY_PLATE_NO", TypeName = "VARCHAR2(100)", Order = 12)]
    public string AgencyPlateNo  get; set; 
    [Column("AGENCY_COVER_AMOUNT", TypeName = "NUMBER(24,2)", Order = 13)]
    public double? AgencyCoverAmount  get; set; 
    [StringLength(100)]
    [Column("MERSIS_NO", TypeName = "VARCHAR2(100)", Order = 14)]
    public string MersisNo  get; set; 
    [StringLength(100)]
    [Column("TECH_PERSONEL_NO", TypeName = "VARCHAR2(100)", Order = 15)]
    public string TechPersonelNo  get; set; 
    [StringLength(100)]
    [Column("TECH_PERSONEL_NAME", TypeName = "VARCHAR2(100)", Order = 16)]
    public string TechPersonelName  get; set; 
    [Column("COVER_END_DATE", TypeName = "DATE", Order = 17)]
    public DateTime? CoverEndDate  get; set; 
    [Column("BRANCH_NUMBER", TypeName = "NUMBER(10,0)", Order = 18)]
    public long? BranchNumber  get; set; 
    [Column("ACTION_NUMBER", TypeName = "NUMBER(10,0)", Order = 19)]
    public long? ActionNumber  get; set; 
    [Column("CLUB_PARTICIPATION_COUNT", TypeName = "NUMBER(10,0)", Order = 20)]
    public long? ClubParticipationCount  get; set; 
    [Column("AGENCY_CONTRACT_DATE", TypeName = "DATE", Order = 21)]
    public DateTime? AgencyContractDate  get; set; 
    [StringLength(200)]
    [Column("KEP_ADDRESS", TypeName = "VARCHAR2(200)", Order = 22)]
    public string KepAddress  get; set; 

【讨论】:

PS : 如果您的表有多个主键,您必须使用 fluent API 设置 PK【参考方案22】:

最简单的方法是EF,逆向工程师。 http://msdn.microsoft.com/en-US/data/jj593170

【讨论】:

【参考方案23】:

我喜欢使用私有本地成员和公共访问器/修改器来设置我的课程。 所以我修改了上面 Alex 的脚本,让感兴趣的人也能做到这一点。

declare @TableName sysname = 'TABLE_NAME'
declare @result varchar(max) = 'public class ' + @TableName + '
'

SET @result = @result + 
'
    public ' + @TableName + '()
    
';

select @result = @result + '
    private ' + ColumnType + ' ' + ' m_' + stuff(replace(ColumnName, '_', ''), 1, 1, lower(left(ColumnName, 1))) + ';'
from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by column_id

SET @result = @result + '
'

select @result = @result + '
    public ' + ColumnType + ' ' + ColumnName + '  get  return m_' + stuff(replace(ColumnName, '_', ''), 1, 1, lower(left(ColumnName, 1))) + '; set m_' + stuff(replace(ColumnName, '_', ''), 1, 1, lower(left(ColumnName, 1))) + ' = value; ' from
(
    select 
        replace(col.name, ' ', '_') ColumnName,
        column_id,
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'string'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'string'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'string'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        end ColumnType
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
    where object_id = object_id(@TableName)
) t
order by column_id

set @result = @result  + '
'

print @result

【讨论】:

【参考方案24】:

对之前解决方案的一个小补充: object_id(@TableName) 仅在您使用默认架构时才有效。

(Select id from sysobjects where name = @TableName)

只要@tableName 是唯一的,就可以在任何架构中工作。

【讨论】:

【参考方案25】:

如果它对其他任何人有用,使用属性映射的 Code-First 方法,我想要一些只需要在对象模型中绑定实体的东西。所以感谢 Carnotaurus 的回答,我根据他们自己的建议对其进行了扩展并进行了一些调整。

因此,这依赖于包含两个部分的解决方案,这两个部分都是 SQL 标量值函数:

    “初始大写”函数(取自: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/8a58dbe1-7a4b-4287-afdc-bfecb4e69b23/similar-to-initcap-in-sql-server-tsql 并稍作修改以满足我的需要)
ALTER function [dbo].[ProperCase] (@cStringToProper varchar(8000))
returns varchar(8000)
as
begin
   declare  @Position int
    select @cStringToProper = stuff(lower(@cStringToProper) , 1 , 1 , upper(left(@cStringToProper , 1)))
        , @Position = patindex('%[^a-zA-Z][a-z]%' , @cStringToProper collate Latin1_General_Bin)

   while @Position > 0
         select @cStringToProper = stuff(@cStringToProper , @Position , 2 , upper(substring(@cStringToProper , @Position , 2)))
              , @Position = patindex('%[^a-zA-Z][a-z]%' , @cStringToProper collate Latin1_General_Bin)

  select @cStringToProper = replace(@cStringToProper, '_','')

   return @cStringToProper
end

    输出函数本身,它通过以下方式扩展 Carnotaurus 的解决方案:

    正确输出换行符 执行一些基本的制表 写出适当的 [Table] 映射(按照建议) 写出适当的 [Column] 映射,包括类型名称(按照建议) 允许实体名称与表名不同 修复了当您拥有包含大量列的表时 Print @Result 截断的限制
CREATE FUNCTION [dbo].[GetEntityObject] (@NameSpace NVARCHAR(MAX), @TableName NVARCHAR(MAX), @EntityName NVARCHAR(MAX))  RETURNS NVARCHAR(MAX) AS BEGIN

DECLARE @result NVARCHAR(MAX)

SET @result = @result + 'using System;' + CHAR(13) + CHAR(13) 

IF (@NameSpace IS NOT NULL)  BEGIN
    SET @result = @result + 'namespace ' + @NameSpace  + CHAR(13) + '' + CHAR(13)  END

SET @result = @result + '[Table(name: ' + CHAR(34) + @TableName + CHAR(34) + ')]' + CHAR(13) SET @result = @result + 'public class ' + @EntityName + CHAR(13) + '' + CHAR(13) 

SET @result = @result + '#region Instance Properties' + CHAR(13)  

SELECT @result = @result + CHAR(13)     + '[Column(name: ' + CHAR(34) + OriginalColumnName + CHAR(34) + ', TypeName = ' + CHAR(34) + DataType
+ CHAR(34) + ')]' + CHAR(13)
    + 'public ' + ColumnType + ' ' + ColumnName + '  get; set;  ' + CHAR(13)  FROM (
    SELECT dbo.ProperCase (c.COLUMN_NAME)   AS ColumnName 
        , CASE c.DATA_TYPE   
            WHEN 'bigint' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Int64?' ELSE 'Int64' END
            WHEN 'binary' THEN 'Byte[]'
            WHEN 'bit' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Boolean?' ELSE 'Boolean' END            
            WHEN 'char' THEN 'String'
            WHEN 'date' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                        
            WHEN 'datetime' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                        
            WHEN 'datetime2' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                        
            WHEN 'datetimeoffset' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTimeOffset?' ELSE 'DateTimeOffset' END                                    
            WHEN 'decimal' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                    
            WHEN 'float' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Single?' ELSE 'Single' END                                    
            WHEN 'image' THEN 'Byte[]'
            WHEN 'int' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Int32?' ELSE 'Int32' END
            WHEN 'money' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                                
            WHEN 'nchar' THEN 'String'
            WHEN 'ntext' THEN 'String'
            WHEN 'numeric' THEN
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                                            
            WHEN 'nvarchar' THEN 'String'
            WHEN 'real' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Double?' ELSE 'Double' END                                                                        
            WHEN 'smalldatetime' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                                    
            WHEN 'smallint' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Int16?' ELSE 'Int16'END            
            WHEN 'smallmoney' THEN  
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Decimal?' ELSE 'Decimal' END                                                                        
            WHEN 'text' THEN 'String'
            WHEN 'time' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'TimeSpan?' ELSE 'TimeSpan' END                                         
            WHEN 'timestamp' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'DateTime?' ELSE 'DateTime' END                                    
            WHEN 'tinyint' THEN 
                CASE C.IS_NULLABLE
                    WHEN 'YES' THEN 'Byte?' ELSE 'Byte' END                                                
            WHEN 'uniqueidentifier' THEN 'Guid'
            WHEN 'varbinary' THEN 'Byte[]'
            WHEN 'varchar' THEN 'String'
            ELSE 'Object'
        END AS ColumnType
        , c.ORDINAL_POSITION        , c.COLUMN_NAME as OriginalColumnName       ,c.DATA_TYPE as DataType

FROM    INFORMATION_SCHEMA.COLUMNS c WHERE   c.TABLE_NAME = @TableName) t ORDER BY t.ORDINAL_POSITION

SET @result = @result + CHAR(13) + '#endregion Instance Properties' + CHAR(13)  

SET @result = @result  + '' + CHAR(13)

IF (@TableName IS NOT NULL)  BEGIN
    SET @result = @result + CHAR(13) + ''  END

return @result END

在 MS SQL Management Studio 中使用:

SELECT dbo.GetEntityObject('MyNameSpace', 'MyTableName', 'MyEntityName')

将生成一个列值,您可以将其复制并粘贴到 Visual Studio 中。

如果它对任何人都有帮助,那就太好了!

【讨论】:

我没有添加 [Key] 属性,因为手动添加它很容易。此外,您可能会遇到错误,即无法将 Real 映射到 Edm.Double[Nullable=True,DefaultValue=]。如果是这种情况,请尝试修改相关属性或将 Real 映射到 Single 的函数。【参考方案26】:

Java 类生成

declare @TableName varchar(max) = 'Restaurants'
declare @Templete varchar(max) = ' 
     public @ColumnType @ColumnName ; // @ColumnDesc  
     public @ColumnType get@ColumnName()
     
        return this.@ColumnName;
     
     public void set@ColumnName(@ColumnType @ColumnName)
     
        this.@ColumnName=@ColumnName;
     

     '
declare @before varchar(max)='public class  @TableName  
'
   
declare @after varchar(max)='
'



declare @result varchar(max)

set @before =replace(@before,'@TableName',@TableName)

set @result=@before

select @result = @result 
+ replace(replace(replace(replace(replace(@Templete,'@ColumnType',ColumnType) ,'@ColumnName',ColumnName) ,'@ColumnDesc',ColumnDesc),'@ISPK',ISPK),'@max_length',max_length)

from  
(
    select 
    column_id,
    replace(col.name, ' ', '_') ColumnName,
    typ.name as sqltype,
    typ.max_length,
    is_identity,
    pkk.ISPK, 
        case typ.name 
            when 'bigint' then 'long'
            when 'binary' then 'byte[]'
            when 'bit' then 'bool'
            when 'char' then 'String'
            when 'date' then 'DateTime'
            when 'datetime' then 'DateTime'
            when 'datetime2' then 'DateTime'
            when 'datetimeoffset' then 'DateTimeOffset'
            when 'decimal' then 'decimal'
            when 'float' then 'float'
            when 'image' then 'byte[]'
            when 'int' then 'int'
            when 'money' then 'decimal'
            when 'nchar' then 'char'
            when 'ntext' then 'string'
            when 'numeric' then 'decimal'
            when 'nvarchar' then 'String'
            when 'real' then 'double'
            when 'smalldatetime' then 'DateTime'
            when 'smallint' then 'short'
            when 'smallmoney' then 'decimal'
            when 'text' then 'String'
            when 'time' then 'TimeSpan'
            when 'timestamp' then 'DateTime'
            when 'tinyint' then 'byte'
            when 'uniqueidentifier' then 'Guid'
            when 'varbinary' then 'byte[]'
            when 'varchar' then 'string'
            else 'UNKNOWN_' + typ.name
        END + CASE WHEN col.is_nullable=1 AND typ.name NOT IN ('binary', 'varbinary', 'image', 'text', 'ntext', 'varchar', 'nvarchar', 'char', 'nchar') THEN '?' ELSE '' END ColumnType,
      isnull(colDesc.colDesc,'') AS ColumnDesc 
    from sys.columns col
        join sys.types typ on
            col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id
            left join
            (
                SELECT c.name  AS 'ColumnName', CASE WHEN dd.pk IS NULL THEN 'false' ELSE 'true' END ISPK           
                FROM        sys.columns c
                    JOIN    sys.tables  t   ON c.object_id = t.object_id    
                    LEFT JOIN (SELECT   K.COLUMN_NAME , C.CONSTRAINT_TYPE as pk  
                        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K 
                            LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS C
                        ON K.TABLE_NAME = C.TABLE_NAME
                            AND K.CONSTRAINT_NAME = C.CONSTRAINT_NAME
                            AND K.CONSTRAINT_CATALOG = C.CONSTRAINT_CATALOG
                            AND K.CONSTRAINT_SCHEMA = C.CONSTRAINT_SCHEMA            
                        WHERE K.TABLE_NAME = @TableName) as dd
                     ON dd.COLUMN_NAME = c.name
                 WHERE       t.name = @TableName       
            ) pkk  on ColumnName=col.name

    OUTER APPLY (
    SELECT TOP 1 CAST(value AS NVARCHAR(max)) AS colDesc
    FROM
       sys.extended_properties
    WHERE
       major_id = col.object_id
       AND
       minor_id = COLUMNPROPERTY(major_id, col.name, 'ColumnId')
    ) colDesc      
    where object_id = object_id(@TableName)

    ) t

    set @result=@result+@after

    select @result
    --print @result

【讨论】:

【参考方案27】:

由于之前没有人提到过,所以还有 Scaffold-DbContext

在 NuGet 包管理器控制台中键入以下内容: Scaffold-DbContext "Your Connection String" Microsoft.EntityFrameworkCore.SqlServer -OutputDir "Output Directory"

【讨论】:

【参考方案28】:

从 Postgres 数据库生成

DO $$ DECLARE v_tabela varchar; DECLARE v_cursor_colunas record; DECLARE v_nome_coluna varchar; DECLARE v_classe VARCHAR; DECLARE v_tipo VARCHAR; DECLARE v_schema_name VARCHAR; BEGIN v_schema_name := 'my-schema'; v_tabela := 'my-table'; select table_name INTO v_tabela from information_schema.tables where table_schema = v_schema_name and table_type = 'BASE TABLE' and table_name = v_tabela; v_classe := E'\r\n' || 'public class ' || v_tabela || ' ' || E'\r\n'; FOR v_cursor_colunas IN SELECT column_name as coluna, is_nullable as isnull, data_type as tipo, character_maximum_length as tamanho FROM information_schema.columns WHERE table_schema = v_schema_name AND table_name = v_tabela LOOP IF v_cursor_colunas.tipo='character varying' THEN v_tipo:= 'string'; ELSIF v_cursor_colunas.tipo='character' and v_cursor_colunas.tamanho=1 THEN v_tipo:= 'char'; ELSIF v_cursor_colunas.tipo='character' and v_cursor_colunas.tamanho<>1 THEN v_tipo:= 'string'; ELSIF v_cursor_colunas.tipo like 'timestamp%' THEN v_tipo:= 'DateTime'; IF v_cursor_colunas.isnull='YES' then v_tipo:= 'DateTime?'; END IF; ELSIF v_cursor_colunas.tipo='boolean' THEN v_tipo:= 'bool'; IF v_cursor_colunas.isnull='YES' then v_tipo:= 'bool?'; END IF; ELSIF v_cursor_colunas.tipo='integer' THEN v_tipo:= 'int'; IF v_cursor_colunas.isnull='YES' then v_tipo:= 'int?'; END IF; ELSIF v_cursor_colunas.tipo='numeric' THEN v_tipo:= 'double'; IF v_cursor_colunas.isnull='YES' then v_tipo:= 'double?'; END IF; ELSIF v_cursor_colunas.tipo='text' THEN v_tipo:= 'string'; ELSE v_tipo:= 'another'; END IF; v_nome_coluna := v_cursor_colunas.coluna; v_classe := v_classe || 'public ' || v_tipo || ' ' || v_cursor_colunas.coluna || ' get; set; ' || E'\r\n'; END LOOP;

v_classe := v_classe || E'\r\n' || ''; 提高通知 '%' , v_classe; 结束$$;

【讨论】:

【参考方案29】:

Postgres DB 的另一种解决方案 -> C#

兼容NpgSQL 已添加DataAnnotations
    SELECT
            CASE 
                WHEN c.is_nullable ='NO'  THEN '[Required]'||chr(10)
                ELSE '' END
            ||CASE 
                WHEN c.data_type = 'character varying' THEN format('[StringLength(%s)]',c.character_maximum_length)||chr(10)
                ELSE '' END
            ||'public '
            ||CASE 
                WHEN c.data_type = 'integer' THEN 'int'
                WHEN c.data_type = 'boolean' THEN 'bool'
                WHEN c.data_type = 'double precision' THEN 'double'
                WHEN c.data_type = 'uuid' THEN 'Guid'
                WHEN c.data_type = 'character varying' THEN 'string'
                WHEN c.data_type = 'timestamp without time zone' THEN 'DateTime'    
                WHEN c.data_type = 'bigint' THEN 'long'   
                WHEN c.data_type = 'bytea' THEN 'byte[]'    
            ELSE 'object' END
            ||CASE
                WHEN c.is_nullable='YES' AND NOT  c.data_type = 'character varying' THEN '? '
                ELSE ' ' END
            ||c.column_name||' get;set;'
            ,c.*
    FROM information_schema."columns" c
    WHERE 1=1
    AND c.table_name='YOUR_TABLE_NAME'


【讨论】:

【参考方案30】:

只要您的表格包含两列并且被称为“tblPeople”之类的名称,您就可以做到。

您始终可以编写自己的 SQL 包装器。我实际上更喜欢这样做,我讨厌以任何方式生成的代码。

也许创建一个DAL 类,并有一个名为GetPerson(int id) 的方法,用于查询该人的数据库,然后从结果集中创建您的Person 对象。

【讨论】:

以上是关于从数据库表生成类的主要内容,如果未能解决你的问题,请参考以下文章

如何从 C# 类生成数据库表?

.net 从数据库表运行时生成类

在Eclipse中连接数据库查看数据表从数据库表生成实体类

从对象定义生成数据库表

spring boot 从入门到精通( 二)通过实体类生成数据库表的方式

visual studio 2019从mysql数据库表通过命令自动生成实体类模型