4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

EntityFramework Core 自分用メモ

Last updated at Posted at 2020-09-12

デスクトップにテキストでおいてあったけどなくしそうだったのでメモ。
※参考にしないでください

#####⓪DBマイグレ

  • 初回
    Enable-Migrations

  • アップデート用ファイル作成
    Add-Migration 投稿名

  • 実行
    Update-Database -Verbose

####Entity Framework Core アノテーション

#####①[NotMapped]:DBに追加しないModelのプロパティ

#####②主キー
 単体の場合:[Key]
   modelBuilder.Entity<モデル名>().HasKey(c => c.キー名);
 複合キー :
   modelBuilder.Entity<モデル名>().HasKey(c => new { c.キー名1, c.キー名2 );
   
#####③データの自動生成
[DatabaseGenerated(DatabaseGeneratedOption.None)] 
 自動生成しない(主キーなどを自分の思い通り設定したい場合便利?)
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
 レコード追加時自動で割り振り
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
 追加更新時に自動で割り振り

#####④Not Null制約
 [Required]

#####⑤最大長
 [MaxLength(500)]

#####⑥楽観的排他制御
 [ConcurrencyCheck]:指定したフィールドが楽観的排他チェックの対処対象となる      
           DbUpdateConcurrencyExceptionが発生
[Timestamp]:行が更新追加された際にタイムスタンプが保存される行
       排他チェックの対象となる→DbUpdateConcurrencyExceptionが発生
#####⑦シャドウ プロパティ
 モデルでは定義されてないけど、モデルのプロパティとして利用出来るよ!ってやつ?
  modelBuilder.Entity<クラス名>().Property("シャドウプロパティ名");

利用方法
 context.Entry(モデルが入った変数).Property("シャドウプロパティ名").CurrentValue = DateTime.Now;
 var XXXX = context.XXXX.OrderBy(b => EF.Property(b, "シャドウプロパティ名"));
 
使い道が今一わからん・・・?

#####⑧リレーションシップ
 https://docs.microsoft.com/ja-jp/ef/core/modeling/relationships
 
 ア.完全に定義されたリレーションシップ

sample.cs
	public class Blog
	{
	    public int BlogId { get; set; }
	    public string Url { get; set; }

	    public List<Post> Posts { get; set; }
	}

	public class Post
	{
	    public int PostId { get; set; }
	    public string Title { get; set; }
	    public string Content { get; set; }

	    public int BlogId { get; set; }
	    public Blog Blog { get; set; }
	}

 イ.外部キー プロパティ

sample.cs
	public class Blog
	{
	    public int BlogId { get; set; }
	    public string Url { get; set; }

	    public List<Post> Posts { get; set; }
	}

	public class Post
	{
	    public int PostId { get; set; }
	    public string Title { get; set; }
	    public string Content { get; set; }

	    public Blog Blog { get; set; }
	}

 ウ.単一のナビゲーション プロパティ

sample.cs
	public class Blog
	{
	    public int BlogId { get; set; }
	    public string Url { get; set; }

	    public List<Post> Posts { get; set; }
	}

	public class Post
	{
	    public int PostId { get; set; }
	    public string Title { get; set; }
	    public string Content { get; set; }
	}

 エ.データ注釈
  ①外部キーの名前が完全に定義されたリレーションシップのような命名に寄らない場合
  [ForeignKey("外部キーの名前")]

sample.cs
		public class Blog
		{
		    public int BlogId { get; set; }
		    public string Url { get; set; }

		    public List<Post> Posts { get; set; }
		}

		public class Post
		{
		    public int PostId { get; set; }
		    public string Title { get; set; }
		    public string Content { get; set; }

		    public int BlogForeignKey { get; set; }

		    [ForeignKey("BlogForeignKey")]
		    public Blog Blog { get; set; }
		}
②一つのモデルから同じモデルに二つのリンクが張られている場合
 [InverseProperty("リンク先のモデルのプロパティ名")]
sample.cs
		public class Post
		{
		    public int PostId { get; set; }
		    public string Title { get; set; }
		    public string Content { get; set; }

		    public int AuthorUserId { get; set; }
		    public User Author { get; set; }

		    public int ContributorUserId { get; set; }
		    public User Contributor { get; set; }
		}

		public class User
		{
		    public string UserId { get; set; }
		    public string FirstName { get; set; }
		    public string LastName { get; set; }

		    [InverseProperty("Author")]
		    public List<Post> AuthoredPosts { get; set; }

		    [InverseProperty("Contributor")]
		    public List<Post> ContributedToPosts { get; set; }
		}

 オ.複合外部キー(Fluentを使うしかない?)
modelBuilder.Entity<多の方のモデル名>()
.HasOne(s => s.1の方のモデル名)
.WithMany(c => c.1の方のプロパティ名)
.HasForeignKey(s => new { s.多の方のプロパティ名, s.多の方のプロパティ名 });

 カ.多対多

sample.cs
	class MyContext : DbContext
	{
	    public DbSet<Post> Posts { get; set; }
	    public DbSet<Tag> Tags { get; set; }

	    protected override void OnModelCreating(ModelBuilder modelBuilder)
	    {
	        modelBuilder.Entity<PostTag>()
	            .HasKey(t => new { t.PostId, t.TagId });

	        modelBuilder.Entity<PostTag>()
	            .HasOne(pt => pt.Post)
	            .WithMany(p => p.PostTags)
	            .HasForeignKey(pt => pt.PostId);

	        modelBuilder.Entity<PostTag>()
	            .HasOne(pt => pt.Tag)
	            .WithMany(t => t.PostTags)
	            .HasForeignKey(pt => pt.TagId);
	    }
	}

	public class Post
	{
	    public int PostId { get; set; }
	    public string Title { get; set; }
	    public string Content { get; set; }

	    public List<PostTag> PostTags { get; set; }
	}

	public class Tag
	{
	    public string TagId { get; set; }

	    public List<PostTag> PostTags { get; set; }
	}

	public class PostTag
	{
	    public int PostId { get; set; }
	    public Post Post { get; set; }

	    public string TagId { get; set; }
	    public Tag Tag { get; set; }
	}

#####⑨INDEX
modelBuilder.Entity<クラス名>().HasIndex(b => b.Indexを張るプロパティ名);
ユニークにしたい場合.IsUnique()
複数も可.HasIndex(p => new { p.プロパティ名1, p.プロパティ名2 });

#####⑩自動プロパティ・バッキングフィールド
 DBから展開する場合は、アクセサを使わず直接バッキングフィールドに書き込まれる(ようだ)

sample.cs
public class Blog
{
    private string _url; //←コレの命名規則は_<camel-cased property name> とかm_<camel-cased property name>

    public int BlogId { get; set; }

    public string Url
    {
        get { return _url; }
        set { _url = value; }
    }
}

#####⑪値の変換
 作例のEnumの名前の方で保存されるよってこった 使い道は・・・??

sample.cs
	    public class Rider
		{
		   public int Id { get; set; }
		   public EquineBeast Mount { get; set; }
		}

		public enum EquineBeast
		{
		   Donkey,
		   Mule,
		   Horse,
		   Unicorn
		}
	protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Rider>()
        .Property(e => e.Mount)
        .HasConversion(
            v => v.ToString(),
            v => (EquineBeast)Enum.Parse(typeof(EquineBeast), v));
}

#####⑫所有エンティティ型
 入れ子のように使える。実テーブルは一個

sample.cs
	[Owned]
	public class StreetAddress
	{
	    public string Street { get; set; }
	    public string City { get; set; }
	}
	public class Order
	{
	    public int Id { get; set; }
	    public StreetAddress ShippingAddress { get; set; }
	}

OnModelCreatingに

sample.cs
            #region OwnsOne
            modelBuilder.Entity<Order>().OwnsOne(p => p.ShippingAddress);
            #endregion

            #region OwnsOneString
            modelBuilder.Entity<Order>().OwnsOne(typeof(StreetAddress), "ShippingAddress");
            #endregion

            #region ColumnNames
            modelBuilder.Entity<Order>().OwnsOne(
                o => o.ShippingAddress,
                sa =>
                {
                    sa.Property(p => p.Street).HasColumnName("ShipsToStreet");
                    sa.Property(p => p.City).HasColumnName("ShipsToCity");
                });
            #endregion

####以降はDBへの制約

#####⑭テーブル マッピング

sample.cs
  [Table("blogs")]
  [Table("blogs", Schema = "blogging")] //スキーマの設定

#####⑮nvarchar(max)列マッピング

sample.cs
 [Column("blog_id")]

#####⑯データの種類
  [Column(TypeName = "varchar(200)")] decimal(5, 2) nvarchar(max) DateTime
  使える種類はDBによって異なる
#####⑰主キー
    [Key]
    命名したい場合

sample.cs
        modelBuilder.Entity<Blog>()
            .HasKey(b => b.BlogId)
            .HasName("PrimaryKey_BlogId");

#####⑱既定のスキーマ

sample.cs
   modelBuilder.HasDefaultSchema("blogging");

#####⑲計算列
 DBに計算列は作られないが使い道が・・・?

sample.cs
	class MyContext : DbContext
	{
	    public DbSet<Person> People { get; set; }

	    protected override void OnModelCreating(ModelBuilder modelBuilder)
	    {
	        modelBuilder.Entity<Person>()
	            .Property(p => p.DisplayName)
	            .HasComputedColumnSql("[LastName] + ', ' + [FirstName]");
	    }
	}

	public class Person
	{
	    public int PersonId { get; set; }
	    public string FirstName { get; set; }
	    public string LastName { get; set; }
	    public string DisplayName { get; set; }
	}

#####⑳シーケンス
 ※特定のテーブルに関連付けはされない

sample.cs
   modelBuilder.HasSequence<int>("OrderNumbers");

#####㉑既定値 初期値

sample.cs
	class MyContext : DbContext
	{
	    public DbSet<Blog> Blogs { get; set; }

	    protected override void OnModelCreating(ModelBuilder modelBuilder)
	    {
	        modelBuilder.Entity<Blog>()
	            .Property(b => b.Rating)
	            .HasDefaultValue(3);
	    }
	}

	public class Blog
	{
	    public int BlogId { get; set; }
	    public string Url { get; set; }
	    public int Rating { get; set; }
	}

※SQL フラグメントを利用することも出来る。

sample.cs
.HasDefaultValueSql("getdate()");

#####㉒インデックス

sample.cs
        modelBuilder.Entity<Blog>()
            .HasIndex(b => b.Url)
            .HasName("Index_Url");

#####㉓フィルター

sample.cs
        modelBuilder.Entity<Blog>()
            .HasIndex(b => b.Url)
            .HasFilter("[Url] IS NOT NULL");

#####㉔外部キー制約

sample.cs
	class MyContext : DbContext
	{
	    public DbSet<Blog> Blogs { get; set; }
	    public DbSet<Post> Posts { get; set; }

	    protected override void OnModelCreating(ModelBuilder modelBuilder)
	    {
	        modelBuilder.Entity<Post>()
	            .HasOne(p => p.Blog)
	            .WithMany(b => b.Posts)
	            .HasForeignKey(p => p.BlogId)
	            .HasConstraintName("ForeignKey_Post_Blog");
	    }
	}

	public class Blog
	{
	    public int BlogId { get; set; }
	    public string Url { get; set; }

	    public List<Post> Posts { get; set; }
	}

	public class Post
	{
	    public int PostId { get; set; }
	    public string Title { get; set; }
	    public string Content { get; set; }

	    public int BlogId { get; set; }
	    public Blog Blog { get; set; }
	}
4
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?