7

"データベースファースト"モードを試して、Entity Framework 4.1を使い始めました。 EFが "ADO.Net DbContext Generator"でModelクラスを生成するとき、[Key]属性を持つクラスの主キーを識別すべきではないでしょうか?これがなければ、T4 MVCScaffoldingと互換性がないように見えます。Entity Framework 4.1データベースFirstはDbContext T4生成クラスにプライマリキーを追加しません

はここで詳細です:エンティティデータモデルデザイナーGUIを使用して

、私は私の既存のデータベースからモデルへの単純な「国」テーブルを追加しました。 GUIは、プライマリキーとして「PK」という名前の単一の整数識別キーフィールドを正しく識別します。しかし、EFが "ADO.Net DbContext Generator"を使用してコードを生成するとき、それはPKを識別しません(つまり、私は新しいユーザーですので、スクリーンショットを追加できません。フィールドを生成されたクラスのキーフィールドとして使用します(以下のコードの抜粋を参照)。

「国」テーブルのCSDL:

<edmx:ConceptualModels> 
    <Schema Namespace="EpiDataModel" Alias="Self" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2008/09/edm"> 
    <EntityContainer Name="EpiModelEntities" annotation:LazyLoadingEnabled="true"> 
     <EntitySet Name="countries" EntityType="EpiDataModel.country" /> 
    </EntityContainer> 
    <EntityType Name="country"> 
     <Key> 
     <PropertyRef Name="PK" /> 
     </Key> 
     <Property Name="PK" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" /> 
     <Property Name="Abbreviation" Type="String" Nullable="false" MaxLength="200" Unicode="false" FixedLength="false" /> 
     <Property Name="Name" Type="String" MaxLength="1024" Unicode="false" FixedLength="false" /> 
     <Property Name="Description" Type="String" MaxLength="1024" Unicode="false" FixedLength="false" /> 
     <Property Name="Sequence" Type="Int32" /> 
    </EntityType> 
    </Schema> 
</edmx:ConceptualModels> 

ここで自動生成されたコードです:私はMVCScaffolding T4テンプレートを使用してコントローラを足場しようとすると、

//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated from a template. 
// 
// Manual changes to this file may cause unexpected behavior in your application. 
// Manual changes to this file will be overwritten if the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

using System; 
using System.Collections.Generic; 

namespace MvcApplication1.Areas.Epi.Models 
{ 
    public partial class country 
    { 
     public int PK { get; set; } 
     public string Abbreviation { get; set; } 
     public string Name { get; set; } 
     public string Description { get; set; } 
     public Nullable<int> Sequence { get; set; } 
    } 
} 

は、これが問題になります。 「プロパティはプライマリキーのように見えません」というエラーが表示されます。 NuGetパッケージマネージャコンソールからのコマンドと出力は以下の通りです:

PM> scaffold controller MvcApplication1.Areas.Epi.Models.country -Area Epi -NoChildItems -DbContextType MvcApplication1.Areas.Epi.Models.EpiModelEntities -Force 
Scaffolding countriesController... 
Get-PrimaryKey : Cannot find primary key property for type 'MvcApplication1.Areas.Epi.Models.country'. No properties appear to be primary keys. 
At C:\work\EPI\EPIC_MVC3\sandbox\MvcApplication1\packages\MvcScaffolding.1.0.6\tools\Controller\MvcScaffolding.Controller.ps1:74 char:29 
+ $primaryKey = Get-PrimaryKey <<<< $foundModelType.FullName -Project $Project -ErrorIfNotFound 
    + CategoryInfo   : NotSpecified: (:) [Get-PrimaryKey], Exception 
    + FullyQualifiedErrorId : T4Scaffolding.Cmdlets.GetPrimaryKeyCmdlet 

しかし、私は手動でフィールドに[キー]属性を追加するために生成されたクラスを変更する場合は、上に示したまったく同じ足場コマンドが正常に動作します:

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; // manually added 

namespace MvcApplication1.Areas.Epi.Models 
{ 
    public partial class country 
    { 
     [Key]      // manually added 
     public int PK { get; set; } 
     public string Abbreviation { get; set; } 
     public string Name { get; set; } 
     public string Description { get; set; } 
     public Nullable<int> Sequence { get; set; } 
    } 
} 

なぜEFデータベースファーストとT4 MVCScaffoldingが一緒に素敵をプレイされていませんか?また、足場の問題がなくても、EFクラスはキーフィールドが何であるかを知る必要はありませんか?

答えて

5

T4テンプレートでは、テンプレートから生成されたクラスにはデータアノテーションは必要ないため、データアノテーションは使用されません。マッピングはXMLファイルではなくコードで定義されているため、EFにも必要ありません。あなたはどちらかなければならないデータの注釈が必要な場合:それらを使用する

  • 変更T4テンプレートを(これはEFのメタデータモデルを理解する必要があります)
  • テンプレートを使用して、手動に
  • 最初の代わりに使用buddy classesをコードを使用しないでください。データ注釈を追加し、誰かがこれをしたいならば足場は彼らに
+0

おかげラディスラフ。 T4テンプレートを変更することは、今私が試みたいことを超えています。私はバディクラス(http://stackoverflow.com/questions/4915957/using-system-componentmodel-dataannotations-with-entity-framework-4-0/に従ってください)を試しました。私はコンパイルしてエラーなしでプロジェクトをビルドすることができましたが、 MVCScaffoldingパッケージはまだ動作しませんでした。私はこれをMVCScaffolding CodePlexプロジェクト(http://mvcscaffolding.codeplex.com/discussions/284993)の下でディスカッショントピックとして追加しました。私が大規模な既存のDBにマッピングしているため、Code Firstはオプションではありません。 –

+0

利用可能なT4テンプレートの修正版はありませんか? – Saber

2

を認識することを願って、私は、ヘクタール james mannings github これらのテンプレートのいくつかの良い面白いのテンプレートを見つけましたより多くの機能を提供しましたが、私がこれらから取り出したビットは次のとおりです。
1)使用法をEntityの先頭に置き換えます。

using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
<# 
    if (efHost.EntityFrameworkVersion >= new Version(4, 4)) 
    { 
     WriteLine("using System.ComponentModel.DataAnnotations.Schema;"); 
    } 
#> 

2とTT)次に、そのプロパティを出力し(この行を見つける。)

<#= Accessibility.ForProperty(property) #> <#= typeUsage #> <#= code.Escape(property) #> { get; set; } 

3)及びプリペンドこのテンプレートコード

var attributes = new List<string>(); 
    var isPartOfPrimaryKey = efHost.EntityType.KeyMembers.Contains(property); 
    var primaryKeyHasMultipleColumns = efHost.EntityType.KeyMembers.Count > 1; 

    if (isPartOfPrimaryKey) 
    { 
     if (primaryKeyHasMultipleColumns) 
     { 
      var columnNumber = efHost.EntityType.KeyMembers.IndexOf(property); 
      attributes.Add(String.Format("[Key, Column(Order = {0})]", columnNumber)); 
     } 
     else 
     { 
      attributes.Add("[Key]"); 
     } 
    } 
    PushIndent(new string(' ', 8)); 
    foreach (var attribute in attributes) 
    { 
     WriteLine(attribute); 
    } 
    ClearIndent(); 
関連する問題