20

ぺたポコキャンプから来ました。PetaPoco には、データベースからモデルを生成する T4 テンプレートがあります。Dapper で利用できる同様のものはありますか?

NuGet を使用して Dapper をインストールし、SqlHelper.cs を追加しましたが、データベースからモデルを生成するものは見つかりませんでした。

4

11 に答える 11

49

私は最近、自分で仕事をするためのSQLクエリを書きました。そして、必要に応じて追加のタイプで更新します。@@@@ と書かれているテーブル名を置き換えるだけです。

多くのテーブルを作成するために、呼び出す一時ストアド プロシージャを作成しました。例えば。 exec createTablePOCO(@tableName)

SELECT 
    'public ' + a1.NewType + ' ' + a1.COLUMN_NAME + ' {get;set;}'
    ,*
FROM (
    /*using top because i'm putting an order by ordinal_position on it. 
    putting a top on it is the only way for a subquery to be ordered*/
    SELECT TOP 100 PERCENT
    COLUMN_NAME,
    DATA_TYPE,
    IS_NULLABLE,
    CASE 
        WHEN DATA_TYPE = 'varchar' THEN 'string'
        WHEN DATA_TYPE = 'datetime' AND IS_NULLABLE = 'NO' THEN 'DateTime'
        WHEN DATA_TYPE = 'datetime' AND IS_NULLABLE = 'YES' THEN 'DateTime?'
        WHEN DATA_TYPE = 'int' AND IS_NULLABLE = 'YES' THEN 'int?'
        WHEN DATA_TYPE = 'int' AND IS_NULLABLE = 'NO' THEN 'int'
        WHEN DATA_TYPE = 'smallint' AND IS_NULLABLE = 'NO' THEN 'Int16'
        WHEN DATA_TYPE = 'smallint' AND IS_NULLABLE = 'YES' THEN 'Int16?'
        WHEN DATA_TYPE = 'decimal' AND IS_NULLABLE = 'NO' THEN 'decimal'
        WHEN DATA_TYPE = 'decimal' AND IS_NULLABLE = 'YES' THEN 'decimal?'
        WHEN DATA_TYPE = 'numeric' AND IS_NULLABLE = 'NO' THEN 'decimal'
        WHEN DATA_TYPE = 'numeric' AND IS_NULLABLE = 'YES' THEN 'decimal?'
        WHEN DATA_TYPE = 'money' AND IS_NULLABLE = 'NO' THEN 'decimal'
        WHEN DATA_TYPE = 'money' AND IS_NULLABLE = 'YES' THEN 'decimal?'
        WHEN DATA_TYPE = 'bigint' AND IS_NULLABLE = 'NO' THEN 'long'
        WHEN DATA_TYPE = 'bigint' AND IS_NULLABLE = 'YES' THEN 'long?'
        WHEN DATA_TYPE = 'tinyint' AND IS_NULLABLE = 'NO' THEN 'byte'
        WHEN DATA_TYPE = 'tinyint' AND IS_NULLABLE = 'YES' THEN 'byte?'
        WHEN DATA_TYPE = 'char' THEN 'string'
        WHEN DATA_TYPE = 'timestamp' THEN 'byte[]'
        WHEN DATA_TYPE = 'varbinary' THEN 'byte[]'
        WHEN DATA_TYPE = 'bit' AND IS_NULLABLE = 'NO' THEN 'bool'
        WHEN DATA_TYPE = 'bit' AND IS_NULLABLE = 'YES' THEN 'bool?'
        WHEN DATA_TYPE = 'xml' THEN 'string'
    END AS NewType
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = '@@@@'
    ORDER BY ORDINAL_POSITION
) as a1
于 2012-07-24T23:41:00.053 に答える
7

カーソルからストアド プロシージャを呼び出す

上記のspマトリックスを組み合わせて(上記の回答を参照)、カーソルから呼び出すと、データベース内のすべてのテーブルのpocoクラスを生成できます

USE YourDataBaseName
GO 
    DECLARE @field1 nvarchar(400)
    DECLARE cur CURSOR LOCAL for

    SELECT TABLE_NAME FROM information_schema.tables
    OPEN cur
    FETCH NEXT FROM cur INTO @field1 --, @field2
    WHILE @@FETCH_STATUS = 0 BEGIN          
        exec Helper_CreatePocoFromTableName @field1 -- , @field2            
        fetch next from cur into @field1 -- , @field2
    END

close cur
deallocate cur

ストアド プロシージャのマトリックスについて言及

matritchies の回答 (上記参照) から sql を取得し、彼が言及したストアド プロシージャを作成し、クラス名も追加するように少し変更しました。Management Studio を Text-Output-Mode にして、列名の出力を削除すると、すべてのクラスのコピー ペースト テキストが得られます。

CREATE PROCEDURE [dbo].[Helper_CreatePocoFromTableName]    
    @tableName varchar(100)
AS
BEGIN
SET NOCOUNT ON;

-- Subquery to return only the copy paste text
Select PropertyColumn from (
    SELECT 1 as rowNr, 'public class ' + @tableName + ' {' as PropertyColumn
    UNION
    SELECT 2 as rowNr, 'public ' + a1.NewType + ' ' + a1.COLUMN_NAME + ' {get;set;}' as PropertyColumn
    -- ,* comment added so that i get copy pasteable output
     FROM 
    (
        /*using top because i'm putting an order by ordinal_position on it. 
        putting a top on it is the only way for a subquery to be ordered*/
        SELECT TOP 100 PERCENT
        COLUMN_NAME,
        DATA_TYPE,
        IS_NULLABLE,
        CASE 
            WHEN DATA_TYPE = 'varchar' THEN 'string'
            WHEN DATA_TYPE = 'nvarchar' THEN 'string' 
            WHEN DATA_TYPE = 'datetime' AND IS_NULLABLE = 'NO' THEN 'DateTime'
            WHEN DATA_TYPE = 'datetime' AND IS_NULLABLE = 'YES' THEN 'DateTime?'
            WHEN DATA_TYPE = 'smalldatetime' AND IS_NULLABLE = 'NO' THEN 'DateTime'
            WHEN DATA_TYPE = 'datetime2' AND IS_NULLABLE = 'NO' THEN 'DateTime'
            WHEN DATA_TYPE = 'smalldatetime' AND IS_NULLABLE = 'YES' THEN 'DateTime?'
            WHEN DATA_TYPE = 'datetime2' AND IS_NULLABLE = 'YES' THEN 'DateTime?'
            WHEN DATA_TYPE = 'int' AND IS_NULLABLE = 'YES' THEN 'int?'
            WHEN DATA_TYPE = 'int' AND IS_NULLABLE = 'NO' THEN 'int'
            WHEN DATA_TYPE = 'smallint' AND IS_NULLABLE = 'NO' THEN 'Int16'
            WHEN DATA_TYPE = 'smallint' AND IS_NULLABLE = 'YES' THEN 'Int16?'
            WHEN DATA_TYPE = 'decimal' AND IS_NULLABLE = 'NO' THEN 'decimal'
            WHEN DATA_TYPE = 'decimal' AND IS_NULLABLE = 'YES' THEN 'decimal?'
            WHEN DATA_TYPE = 'numeric' AND IS_NULLABLE = 'NO' THEN 'decimal'
            WHEN DATA_TYPE = 'numeric' AND IS_NULLABLE = 'YES' THEN 'decimal?'
            WHEN DATA_TYPE = 'money' AND IS_NULLABLE = 'NO' THEN 'decimal'
            WHEN DATA_TYPE = 'money' AND IS_NULLABLE = 'YES' THEN 'decimal?'
            WHEN DATA_TYPE = 'bigint' AND IS_NULLABLE = 'NO' THEN 'long'
            WHEN DATA_TYPE = 'bigint' AND IS_NULLABLE = 'YES' THEN 'long?'
            WHEN DATA_TYPE = 'tinyint' AND IS_NULLABLE = 'NO' THEN 'byte'
            WHEN DATA_TYPE = 'tinyint' AND IS_NULLABLE = 'YES' THEN 'byte?'
            WHEN DATA_TYPE = 'char' THEN 'string'                       
            WHEN DATA_TYPE = 'timestamp' THEN 'byte[]'
            WHEN DATA_TYPE = 'varbinary' THEN 'byte[]'
            WHEN DATA_TYPE = 'bit' AND IS_NULLABLE = 'NO' THEN 'bool'
            WHEN DATA_TYPE = 'bit' AND IS_NULLABLE = 'YES' THEN 'bool?'
            WHEN DATA_TYPE = 'xml' THEN 'string'
        END AS NewType
        FROM INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = @tableName
        ORDER BY ORDINAL_POSITION
        ) AS a1 
    UNION 
    SELECT 3 as rowNr,  '} // class ' + @tableName
    ) as t Order By rowNr asc
END

PS: 私は彼の回答に対する編集の提案としてそれを行ったでしょうが、私の経験では、編集の提案が拒否されることがよくあります。

アップデート

ユーザーchris-w-mcleanは次の変更を提案しました (彼のSuggested-editを参照)。私自身は試していません:

  • SELECT 1 as rowNr, 'public class 'と置き換えますSELECT 1.0 as rowNr, 'public class '
  • SELECT 2 as rowNr, 'public 'と置き換えます SELECT 2 + a1.ORDINAL_POSITION/1000 as rowNr, 'public '
  • SELECT TOP 100 PERCENT COLUMN_NAME,と置き換えます SELECT COLUMN_NAME,
  • IS_NULLABLE, CASEこの行の間に追加cast(ORDINAL_POSITION as float) as ORDINAL_POSITION,
  • 削除するORDER BY ORDINAL_POSITION
  • SELECT 3 asに変更SELECT 3.0 as
于 2013-03-12T19:03:57.800 に答える
5

結果をテキスト出力にパイプする必要がないように、少し最適化したこのバージョンを試してください。代わりに、PRINT ステートメントを使用すると、出力を簡単にコピー/貼り付けできます。また、サブクエリを削除し、nvarchar/ntext 型の宣言を追加しました。

これは単一のテーブル用ですが、ストアド プロシージャに変換して、上記のカーソルの提案のいずれかを使用できます。

SET NOCOUNT ON
DECLARE @tbl as varchar(255)
SET @tbl = '@@@@'

DECLARE @flds as varchar(8000)
SET @flds=''

SELECT -1 as f0, 'public class ' + @tbl + ' {' as f1 into #tmp

INSERT #tmp
SELECT 
    ORDINAL_POSITION, 
    '    public ' + 
    CASE 
        WHEN DATA_TYPE = 'varchar' THEN 'string'
        WHEN DATA_TYPE = 'nvarchar' THEN 'string'
        WHEN DATA_TYPE = 'text' THEN 'string'
        WHEN DATA_TYPE = 'ntext' THEN 'string'
        WHEN DATA_TYPE = 'char' THEN 'string'
        WHEN DATA_TYPE = 'xml' THEN 'string'
        WHEN DATA_TYPE = 'datetime' AND IS_NULLABLE = 'NO' THEN 'DateTime'
        WHEN DATA_TYPE = 'datetime' AND IS_NULLABLE = 'YES' THEN 'DateTime?'
        WHEN DATA_TYPE = 'int' AND IS_NULLABLE = 'YES' THEN 'int?'
        WHEN DATA_TYPE = 'int' AND IS_NULLABLE = 'NO' THEN 'int'
        WHEN DATA_TYPE = 'smallint' AND IS_NULLABLE = 'NO' THEN 'Int16'
        WHEN DATA_TYPE = 'smallint' AND IS_NULLABLE = 'YES' THEN 'Int16?'
        WHEN DATA_TYPE = 'decimal' AND IS_NULLABLE = 'NO' THEN 'decimal'
        WHEN DATA_TYPE = 'decimal' AND IS_NULLABLE = 'YES' THEN 'decimal?'
        WHEN DATA_TYPE = 'numeric' AND IS_NULLABLE = 'NO' THEN 'decimal'
        WHEN DATA_TYPE = 'numeric' AND IS_NULLABLE = 'YES' THEN 'decimal?'
        WHEN DATA_TYPE = 'money' AND IS_NULLABLE = 'NO' THEN 'decimal'
        WHEN DATA_TYPE = 'money' AND IS_NULLABLE = 'YES' THEN 'decimal?'
        WHEN DATA_TYPE = 'bigint' AND IS_NULLABLE = 'NO' THEN 'long'
        WHEN DATA_TYPE = 'bigint' AND IS_NULLABLE = 'YES' THEN 'long?'
        WHEN DATA_TYPE = 'tinyint' AND IS_NULLABLE = 'NO' THEN 'byte'
        WHEN DATA_TYPE = 'tinyint' AND IS_NULLABLE = 'YES' THEN 'byte?'
        WHEN DATA_TYPE = 'timestamp' THEN 'byte[]'
        WHEN DATA_TYPE = 'varbinary' THEN 'byte[]'
        WHEN DATA_TYPE = 'bit' AND IS_NULLABLE = 'NO' THEN 'bool'
        WHEN DATA_TYPE = 'bit' AND IS_NULLABLE = 'YES' THEN 'bool?'
    END + ' ' + COLUMN_NAME + ' {get;set;}'
FROM INFORMATION_SCHEMA.COLUMNS 
        WHERE TABLE_NAME = @tbl

INSERT #tmp SELECT 999, '}'

SELECT @flds=@flds + f1 +'
' from #tmp order by f0

DROP TABLE #tmp

PRINT @flds
于 2016-06-01T01:48:27.537 に答える
4

Dapper自体は、接続オブジェクトに対していくつかの拡張メソッド(Query、Execute)を提供し、「モデルジェネレーター」を備えていません。おそらく、他のフレームワークを使用して、dbスキーマに基づいてPOCOを生成できます。

アップデート:

C#POCOクラスT4テンプレートへのデータベーステーブル

<#@ template language="C#" debug="True" #>

<#@ assembly name="System" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>

<#@ assembly name="Microsoft.SqlServer.ConnectionInfo" #>
<#@ assembly name="Microsoft.SqlServer.Management.Sdk.Sfc" #>
<#@ assembly name="Microsoft.SqlServer.Smo" #>

<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="Microsoft.SqlServer.Management.Smo" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="Microsoft.SqlServer.Management.Common" #>

namespace Namespace
{

<#         
   var databaseName = "testDb";
            var serverConnection = new SqlConnection(
                    @"Data Source=.\SQLEXPRESS; Integrated Security=true; Initial Catalog=" + databaseName);
            var svrConnection = new ServerConnection(serverConnection);

   Server srv = new Server(svrConnection);
            foreach (Table table in srv.Databases[databaseName].Tables)
            {

#>
        class <#= table.Name #>
        {
            <#
                foreach (Column col in table.Columns)
                {
                #>
                    public <#= GetNetDataType(col.DataType.Name) #> <#= col.Name #> { get; set; }
                <#
                }
             #>
        }

<#            }
#>
}



<#+
        public static string GetNetDataType(string sqlDataTypeName)
        {

            switch (sqlDataTypeName.ToLower())
            {
                case "bigint":
                    return "Int64";
                case "binary":
                    return "Byte[]";
                case "bit":
                    return "bool";
                case "char":
                    return "char";
                case "cursor":
                    return string.Empty;
                case "datetime":
                    return "DateTime";
                case "decimal":
                    return "Decimal";
                case "float":
                    return "Double";
                case "int":
                    return "int";
                case "money":
                    return "Decimal";
                case "nchar":
                    return "string";
                case "numeric":
                    return "Decimal";
                case "nvarchar":
                    return "string";
                case "real":
                    return "single";
                case "smallint":
                    return "Int16";
                case "text":
                    return "string";
                case "tinyint":
                    return "Byte";
                case "varbinary":
                    return "Byte[]";
                case "xml":
                    return "string";
                case "varchar":
                    return "string";
                case "smalldatetime":
                    return "DateTime";
                case "image":
                    return "byte[]";

                default:
                    return string.Empty;
            }



        }
#>
于 2012-06-15T18:47:30.933 に答える
2

古いトピックであることは承知していますが、選択できる別の簡単なオプションがあります。

PocoClassGenerator: Mini Dapper の POCO Class Generator (Dapper Contrib をサポート)を使用できます。

  • 現在のデータベースをサポートし、すべてのテーブルとビューが POCO クラス コードを生成します
  • Dapper.Contrib をサポート
  • 複数の RDBMS をサポート:sqlserver,oracle,mysql,postgresql
  • ミニで高速 (わずか 5 秒で 100 テーブルのコードを生成)
  • 各データベース クエリに適切なダイアレクト スキーマ テーブル SQL を使用する

デモ

20190430141947-image.png

スタートを切る

最初 : PocoClassGenerator.cs コードをコピーしてプロジェクトまたは LINQPad に貼り付けます。
またはNuGetからインストール

PM> install-package PocoClassGenerator

2 番目 : Connection を使用して呼び出しGenerateAllTables、印刷します。

using (var connection = Connection)
{
    Console.WriteLine(connection.GenerateAllTables());
}
Dapper Contrib POCO クラスをサポート
  • でメソッドを呼び出すだけですGeneratorBehavior.DapperContrib
using (var conn = GetConnection())
{
    var result = conn.GenerateAllTables(GeneratorBehavior.DapperContrib);
    Console.WriteLine(result);
}

オンライン デモ : POCO Dapper Contrib クラス ジェネレーター GenerateAllTables | .NETフィドル 20190502132948-image.png

コメントを生成
using (var conn = GetConnection())
{
    var result = conn.GenerateAllTables(GeneratorBehavior.Comment);
    Console.WriteLine(result);
}
ビューの生成
using (var conn = GetConnection())
{
    var result = conn.GenerateAllTables(GeneratorBehavior.View);
    Console.WriteLine(result);
}
View と Comment と Dapper.Contrib を生成する
using (var conn = GetConnection())
{
    var result = conn.GenerateAllTables(GeneratorBehavior.View | GeneratorBehavior.Comment | GeneratorBehavior.DapperContrib);
    Console.WriteLine(result);
}
sql で 1 つのクラスを生成する
  1. 1 つのクラスを生成する
using (var connection = Connection)
{
    var classCode = connection.GenerateClass("select * from Table");
    Console.WriteLine(classCode);
}
  1. クラス名を指定
using (var connection = Connection)
{
    var classCode = connection.GenerateClass("with EMP as (select 1 ID,'WeiHan' Name,25 Age) select * from EMP", className: "EMP");
    Console.WriteLine(classCode);
}
DataTablePocoClass

DataTablePocoClassGenerator.csのコード

var dt = new DataTable();
dt.TableName = "TestTable";
dt.Columns.Add(new DataColumn() { ColumnName = "ID", DataType = typeof(string) });

var result = dt.GenerateClass();
var expect =
@"public class TestTable
{
public string ID { get; set; }
}";
Assert.Equal(expect, result);
于 2021-01-07T02:04:15.920 に答える