sql >> データベース >  >> RDS >> Sqlserver

モデルファーストアプローチで構造アノテーションを使用してSQLタイプを日付に設定するにはどうすればよいですか

    構造アノテーション-いいですね。この機能について聞いたのは初めてですが、機能します。試してみました。少し説明しようと思います。

    構造注釈は、EDMXファイルに追加されたランダムなxmlです。 EDMXファイルは実際にはXMLであり、CSDL、MSL、SSDLの4つの部分と、デザイナーのポジショニング要素に関連する部分があります。

    • CSSDは、エンティティとエンティティ間の関連付け(デザイナで定義)を記述します
    • SSDLはテーブルとリレーションを記述します
    • MSLは、CSDLとSSDL間のマッピングについて説明しています

    最初にモデルから開始する場合(モデルからデータベースを生成する場合)、CSDLパーツのみがあり、SSDLが作成されると、SSDLとMSLの両方が自動プロセス(ワークフローで実行されるT4テンプレート)によって生成されます。別のT4テンプレートが生成されます。データベース作成用のSQLスクリプト。

    リンクされたMSDNフォーラムのスレッドで説明されている構造アノテーションはヒントです。 EDMXのCSDL部分に構造アノテーションを配置します(EDMXをXMLとして開く必要があります-ソリューションエクスプローラーでファイルをクリックし、[プログラムから開く]を選択します)。私のテストCSDLは、3つのプロパティを持つ単一のユーザーエンティティについて説明しています(エンティティは、回答の後半のスクリーンショットに表示されます):

    <!-- CSDL content -->
    <edmx:ConceptualModels>
      <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm" 
              xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" 
              xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
              xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
              xmlns:custom="http://tempuri.org/custom"
              Namespace="Model" Alias="Self" >
        <EntityContainer Name="ModelContainer" annotation:LazyLoadingEnabled="true">
          <EntitySet Name="UsersSet" EntityType="Model.User" />
        </EntityContainer>
        <EntityType Name="User">
          <Key>
            <PropertyRef Name="Id" />
          </Key>
          <Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
          <Property Type="String" Name="Login" Nullable="false" />
          <Property Type="DateTime" Name="CreatedAt" Nullable="false">
            <custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
          </Property>
        </EntityType>
      </Schema>
    </edmx:ConceptualModels>
    

    Schemaにカスタム名前空間定義を追加しました 要素:xmlns:custom="http://tempuri.org/custom" CreatedAtのカスタム構造アノテーションを定義しました プロパティ:

    <Property Type="DateTime" Name="CreatedAt" Nullable="false">
       <custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
    </Property>
    

    構造アノテーションに使用される名前空間または要素の名前は重要ではありません。どの名前を使用するかは絶対にあなた次第です。重要なのはedmx:CopyToSSDL="true"だけです。 属性。この属性は、SSDLの作成に使用されるT4テンプレートによって認識され、この要素を取得してSSDLに配置するだけです。生成されたSSDLは次のようになります:

    <Schema Namespace="Model.Store" Alias="Self" 
            Provider="System.Data.SqlClient" ProviderManifestToken="2008" 
            xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" 
            xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
      <EntityContainer Name="ModelStoreContainer">
        <EntitySet Name="UsersSet" EntityType="Model.Store.UsersSet" store:Type="Tables" Schema="dbo" />
      </EntityContainer>
      <EntityType Name="UsersSet">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
        <Property Name="Login" Type="nvarchar(max)" Nullable="false" />
        <Property Name="CreatedAt" Type="datetime" Nullable="false">
          <custom:SqlType xmlns:custom="http://tempuri.org/custom">Date</custom:SqlType>
        </Property>
      </EntityType>
    </Schema>
    

    唯一のポイントは、構造アノテーションをSSDLに移動することでした。すべての注釈は、名前と値のコレクションを介してメタデータでアクセスできます。次に、SQLスクリプトの生成を担当するT4テンプレートを変更して、この注釈を認識し、プロパティで定義されたタイプの代わりに注釈で定義された値を使用する必要があります。テンプレートは次の場所にあります:

    C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
    

    テンプレートファイルを新しい場所にコピーし(元のファイルを変更しないように)、デフォルトのテーブル作成を次のように置き換えます。

    -- Creating table '<#=tableName#>'
    CREATE TABLE <# if (!IsSQLCE) {#>[<#=schemaName#>].<#}#>[<#=tableName#>] (
    <#
            for (int p = 0; p < entitySet.ElementType.Properties.Count; p++)
            {
                EdmProperty prop = entitySet.ElementType.Properties[p];
    #>
        [<#=Id(prop.Name)#>] <#
                if (prop.MetadataProperties.Contains("http://tempuri.org/custom:SqlType"))
                {
                    MetadataProperty annotationProperty = prop.MetadataProperties["http://tempuri.org/custom:SqlType"];
                    XElement e = XElement.Parse(annotationProperty.Value.ToString());
                    string value = e.Value.Trim();
        #>
        <#=value#> <# } else { #> <#=prop.ToStoreType()#> <# } #> <#=WriteIdentity(prop, targetVersion)#> <#=WriteNullable(prop.Nullable)#><#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>
    <#
            }
    #>
    );
    GO
    

    最後のポイントは、SQLスクリプトの生成に使用するテンプレートを変更することです。デザイナでEDMXファイルを開き、モデルのプロパティに移動します(プロパティウィンドウを開いているときにデザイナのどこかをクリックするだけです)。 DDL生成テンプレートを変更したテンプレートに変更します。

    モデルからデータベースを生成を実行します そして、以下を含むSQLスクリプトを作成します:

    -- Creating table 'UsersSet'
    CREATE TABLE [dbo].[UsersSet] (
        [Id]  int  IDENTITY(1,1) NOT NULL,
        [Login]  nvarchar(max)   NOT NULL,
        [CreatedAt]     Date   NOT NULL
    );
    GO
    

    これはおそらく、私が今まで見た中で最も高度で隠された機能です。注釈とカスタムT4テンプレートを併用すると、クラスとSQLの両方の生成を細かく制御できます。これを使用して、たとえばモデルを最初に使用するときにデータベースインデックスや一意のキーを定義したり、生成されたPOCOクラスにいくつかのカスタム属性を選択的に追加したりすることを想像できます。

    これが非常に隠されている理由は、これを使用するためのVSのツールサポートがすぐに使用できないためです。



    1. 以前に削除された番号を自動インクリメントで埋める

    2. SQLServerで外部キー制約のあるテーブルを作成する方法-SQLServer/TSQLチュートリアルパート66

    3. AzureDataStudioを使用してMacでSQLServerデータベースを復元する方法

    4. Oracleパッケージが無効になる状況は何ですか?