Entity Frameworkの小さな知識の共有

10086 ワード

Entity Frameworkと一緒にいる日は痛くて楽しかったです.今日はみんなと1つの楽しみ、2つの苦痛を分かち合います.
まず楽しいことを話しましょう.Entity Frameworkでは、データベースにデータを挿入する際にプライマリ・キー・フィールドが「≪自己増加ID|Index Identification|Essbase_Studio≫」列の場合、エンティティ・オブジェクトに対応する属性に自己付加価値が戻されます.
たとえば、ブログエッセイをデータベースに追加するコードの例を次に示します.

  
    
var blogPost = new BlogPost()
{
Author
= " " ,
Title
= " "
};
using (BlogDbContext context = new BlogDbContext())
{
context.BlogPosts.Add(blogPost);
context.SaveChanges();
return blogPost.ID;
}

SaveChanges()の後、blogPost.IDの値は、データベース内の自増識別列に対応する値です.
Entity Frameworkで生成されたSQL文を見てみましょう.

  
    
exec sp_executesql N ' insert [dbo].[blog_Content]([Title],[Author])
values (@0, @1)
select [ID]
from [dbo].[blog_Content]
where @@ROWCOUNT > 0 and [ID] = scope_identity()
' ,
N
' @0 nvarchar(128),@1 nvarchar(128), ' , @0 = N ' ' , @1 = N ' '

EF通過scope_identity()は自増列の値を取得し,BlogPostのID属性を何も設定せず,EFがIDが自増識別列であると知能的に判断した.
従来はEntity Frameworkが使用されていなかった時代には、ストアド・プロシージャが使用する、ストアド・プロシージャにはパラメータが山積みになっており、エンティティ・オブジェクトの属性値はこれらのパラメータに1つずつ対応付けられ、ストアド・プロシージャが実行する後はParameterDirectionも通過する.Outputのパラメータは、自増IDの値を取得します.
今、Entity Frameworkに物を渡して、データベースに置くと言っています.心配しないで!なんと楽しいことか.
しかし、独りよがりのEntity Frameworkはこの特性で人を楽しませると同時に、少し苦痛を与えている.エンティティクラスにID属性がある限り、データベースは必ず自増識別列に対応していると考えているが、本当に独りよがりだ.ブログエッセイをデータベースに追加すると、この自増IDでエッセイ内容をデータベースに追加しようとしたが(エッセイ内容は別のデータベースに格納され、IDフィールドでエッセイに関連付けられ、自増ではない)、エラーメッセージが表示された.

  
    
Cannot insert the value NULL into column 'ID', 
table 'CNBlogsText.dbo.blog_PostBody'; column does not allow nulls.

EFで生成されたSQL文を見てみましょう.

  
    
exec sp_executesql N ' insert [dbo].[CNBlogsText_blog_PostBody]([Text])
values (@0)
select [ID]
from [dbo].[CNBlogsText_blog_PostBody]
where @@ROWCOUNT > 0 and [ID] = scope_identity()
' ,N ' @0 nvarchar(128) ' , @0 = N ' '

自増列ではなくscopeも来ますidentity().こんな賢いEntity Frameworkでも、こんなばかなことをする.
EFカスタマイズの柔軟性により、BlogDbContextに次のコードを追加すれば、この苦痛を簡単に解消できます.

  
    
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity
< PostBody > ().Property(p => p.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}

また、エンティティークラスのプロパティにタグを付けることで、次のこともできます.

  
    
public class BlogPost
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get ; set ; }
}

2つ目の苦痛は、よく知られているEntity Frameworkが列挙タイプをサポートしていないことです.誰もが知っていますが、日焼けを出して恨みを晴らしたいと思っています.
EFは列挙タイプをどう扱うのでしょうか.エンティティクラスに実際に存在する列挙タイプの属性については,EFはそれらを無視し,存在しないと見なす.
この痛みについては、現在解消できない(EFの次のバージョンを待つ)ので、隣の左道で苦痛を軽減するしかないので、「隣の左道」の「移花接木」を見てください.
エンティティークラスのコード:

  
    
public class BlogPost
{
public BlogPostType PostType
{
get { return (BlogPostType)PostTypeEf; }
set { PostTypeEf = ( int )value; }
}
public int PostTypeEf { get ; set ; }
}

EFは列挙タイプを認識しないがintタイプを認識するためPostType Efを追加し,EF専用のみとし,EFの次のバージョンが列挙タイプをサポートする場合に削除する.
BlogDbContextも合わせて修正します.

  
    
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity
< BlogPost > ().Ignore(p => p.PostConfig);
modelBuilder.Entity
< BlogPost > ().Property(p => p.PostTypeEf)
.HasColumnName(
" PostType " );
}

分かち合いが終わって、楽しみはもっと楽しくて、苦痛はもう苦痛ではありません.