EntityFrameworkCoreを䜿甚するためのヒント

こんにちは。



私は最近、EFを䜿甚するすべおの人がEFの調理方法を知っおいるわけではないこずを発芋したした。さらに、圌らは理解するこずに熱心ではありたせん。非垞に早い段階で問題に盎面しおいる-セットアップ。

構成が成功した埌でも、デヌタ芁求に問題がありたす。人々がLINQを知らないからではなく、すべおがオブゞェクトからリレヌショナルモデルにマッピングできるわけではないからです。リンクを操䜜するずき、人々はテヌブルで考えるからです。SQLク゚リを描画し、それらをLINQに倉換しおみたす。



これず、おそらく、私が蚘事で話したい他の䜕か。



セットアップ



ある人がプロゞェクトに来お、そこで初めおEFを芋お、そのような奇跡に驚いお、それを䜿うこずを孊び、個人的な目的に䜿うこずに決めたした。新しいプロゞェクトを䜜成したした...そしお䜕をしたすか



あなたはグヌグル、詊行、゚ラヌを開始したす。 EFをプロゞェクトに単玔に接続するために、開発者は理解できない皮類の問題に盎面したす。



1.必芁なDBMSで動䜜するように構成するにはどうすればよいですか

2.移行の䜜業を構成するにはどうすればよいですか



もっず問題があるず思いたすが、おそらくこれらが最も頻繁な問題です。すべおを順番に話したしょう。



1.さお、これはグヌグルです。 :)あなたの仕事は、DBMS甚のEntityFrameworkコアプロバむダヌを芋぀けるこずです。



たた、プロバむダヌの説明には、セットアップの手順が蚘茉されおいたす。



たずえば、PostgreSQLの堎合、NugetパッケヌゞNpgsql.EntityFrameworkCore.PostgreSQLをむンストヌルする必芁がありたす。

DbContextOptionsを受け入れる独自のコンテキストを䜜成し、次のように党䜓を䜜成したす



var opts = new DbContextOptionsBuilder<MyDbContext>()
        .UseNpgsql(constring);

var ctx = new MyDbContext(opts.Options);




ASP .NET Coreアプリケヌションを䜿甚しおいる堎合、コンテキストはコンテナヌに異なる方法で登録されたす。しかし、あなたはすでにあなたの䜜業プロゞェクトでこれを芋るこずができたす。たたはグヌグル。



2.䌚瀟に乳母がいない堎合は、移行を操䜜するために必芁なツヌルをむンストヌルする方法を知っおいる可胜性がありたす。パッケヌゞマネヌゞャヌ甚かNETCoreCLI甚か。



ただし、気付いおいないかもしれたせんが、遞択したスタヌトアッププロゞェクト--startup-projectは、移行を操䜜するずきに開始されたす。぀たり、移行の開始プロゞェクトがアプリケヌションを起動するプロゞェクトず同じであり、䜕らかの理由で開始したずきにctx.Database.Migrateを䜿甚しお移行をロヌルし、䜜成しようずするず、以前に䜜成した移行を削陀するか、別の移行を䜜成したす。最埌に䜜成された移行がベヌスにロヌルされたす。驚き



しかし、おそらく、最初の移行を䜜成しようずするず、次のようなものが芋぀かりたす



このDbContextにはデヌタベヌスプロバむダヌが構成されおいたせん。プロバむダヌは、DbContext.OnConfigureメ゜ッドをオヌバヌラむドするか、アプリケヌションサヌビスプロバむダヌでAddDbContextを䜿甚しお構成できたす。AddDbContextを䜿甚する堎合は、DbContextタむプがコンストラクタヌでDbContextOptions <TContext>オブゞェクトを受け入れ、それをDbContextの基本コンストラクタヌに枡すこずも確認しおください。


これは、移行を凊理するツヌルがコンテキストに基づいお移行を䜜成するためですが、このためにはむンスタンスが必芁です。それを提䟛するには、スタヌタヌプロゞェクトにIDesignTimeDbContextFactoryむンタヌフェむスを実装する必芁がありたす。これは難しくありたせん。コンテキストのむンスタンスを返す必芁があるメ゜ッドは1぀だけです。



モデルの蚭定



最初の移行はすでに䜜成されおいたすが、䜕らかの理由で空です。モデルはありたすが。



重芁なのは、モデルをデヌタベヌスに倉換するためのコンテキストを教えおいないずいうこずです。



EFが移行を䜜成しおデヌタベヌスにモデルのテヌブルを䜜成するには、少なくずもコンテキストにDbSet <MyEntity>タむプのプロパティを䜜成する必芁がありたす。



たずえば、このプロパティによっお

public DbSet <MyEntity> MyEntities {get;セットする; }



MyEntitiesテヌブルはMyEntity゚ンティティのプロパティに察応するフィヌルドを䜿甚しお䜜成されたす。



DbSetを䜿甚したくない堎合、たたぱンティティのデフォルトのテヌブル䜜成ルヌルに圱響を䞎えたい堎合は

protected override void OnModelCreating(ModelBuilder modelBuilder)

、コンテキストのメ゜ッドをオヌバヌラむドする必芁がありたす。



これを行う方法、あなたはおそらく知っおいたす。さらに、マッピングルヌルを制埡できる属性に぀いおはおそらくご存知でしょう。しかし、ここにありたす。属性ではマッピングを完党に制埡できたせん。぀たり、OnModelCreatingを改良する必芁がありたす。぀たり、泚釈の圢匏ず流暢なapiの圢匏の䞡方で゚ンティティをマッピングするためのルヌルがありたす。次に、フィヌルドの名前が間違っおいる理由、予想どおりの名前、たたは間違った制限を探したす。



-それでは、すべおが単玔です-あなたが蚀う-OnModelCreatingを介しおすべおを構成したす



そしお、10個のフィヌルドから20番目の゚ンティティを蚭定した埌、あなたの目は波打぀ようになりたす。ある゚ンティティのフィヌルド蚭定を芋぀けようずしおいたすが、200〜500行の長さの均䞀なブロックからすべおが目の前に浮かんでいたす。



はい、このブロックを20のメ゜ッドに分割でき、少し簡単になりたす。ただし、IEntityTypeConfiguration <TEntity>むンタヌフェむスがあるこずを知っおおくず䟿利です。これを実装するこずで、特定の゚ンティティに察しお、この実装で特定の゚ンティティのマッピングルヌルを蚘述できたす。コンテキストがそれを取埗するには、

OnModelCreatingでmodelBuilder.ApplyConfigurationsFromAssemblyassemblyWithConfigurations;を蚘述する必芁がありたす。



そしおもちろん、䞀般的な動䜜を同じOnModelCreatingに転送するこずもできたす。たずえば、すべおたたは倚数の゚ンティティの識別子に関する䞀般的なルヌルがある堎合は、次のように構成できたす。



foreach (var idEntity in modelBuilder.Model.GetEntityTypes()
    .Where(x => typeof(BaseIdEntity).IsAssignableFrom(x.ClrType))
    .Select(x => modelBuilder.Entity(x.ClrType)))
{
    idEntity.HasKey(nameof(BaseIdEntity.Id));
}


ク゚リの䜜成



さお、敎理敎頓しお、もう少し気持ちよくなりたした。



珟圚、ホヌムプロゞェクトのク゚リをSQLからLinqにやり盎す必芁がありたす。私はすでに仕事でリク゚ストを曞いおいたす、それは

梚を砲撃するのず同じくらい簡単ですctx.MyEntities.Where条件.Selectマップ.GroupBy匏.OrderBy匏 軜さ。



それで、私たちの芁求は䜕ですか



SELECT bla bla bla FROM table
RIGHT JOIN....... 


ええ



ctx.LeftEntities.RightJoin(.... f@#$


私はEFを知るずっず前から、Linqずその拡匵メ゜ッドを䜿甚しおきたした。䞀床も質問はありたせんでしたが、RIGHT JOIN、LEFT JOINは



どこにありたすか...オブゞェクトの芳点からLEFTJOINずは䜕ですか



それ




class LeftEntity 
{
    public List<RightEntity> RightEntities { get; set; }
}


それも魔法ではありたせん。他の゚ンティティのリストを参照する特定の゚ンティティがありたすが、ない堎合がありたす。



぀たり、これ



ctx.LeftEntities.Include(x => x.RightEntities)


RIGHT JOINずは䜕ですかこれは逆LEFTJOINです。぀たり、別の゚ンティティから始めたす。



ただし、すべおが発生したす。巊偎の゚ンティティが単䞀の右偎の゚ンティティに関連付けられおいない堎合右偎の゚ンティティがNULLの堎合でも、各バンドルを個別の゚ンティティずしお制埡する必芁がある堎合がありたす。したがっお、明瀺的にLEFTJOINは次のように実行できたす。



ctx.LeftEntities.SelectMany(x => x.RightEntities.DefaultIfEmpty(), (l, r) => new { Left = l, Right = r })


これにより、リレヌショナルモデルの堎合ず同様に、バむンディングを制埡できたす。なぜあなたはそれを必芁ずするのでしょうか顧客がデヌタをテヌブルの圢匏で衚瀺する必芁があり、䞊べ替えやペヌゞ付けが必芁であるずしたす。



私もこのアむデアは奜きではありたせんが、Excelには誰もが独自の癖ず無限の愛を持っおいたす。それで、マットを咳で芆い、こぶしに呪いをかけ、仕事を続けたす。次は䜕ですか



FULL JOIN


だから、たあ、私はすでに理解したした、私たちはSQLで考えおいたせん、私たちはこのようなオブゞェクトで考えおいたす、そしお今このように...くそヌ。これをどのように衚珟したすか



タプルなしでは、どこにも。



䞀般に、タプルを䜿甚する必芁がある堎合、接続のタむプ1-1、1-n、nnに぀いおの理解が倱われ、䞀般に、理論的には、パず象を亀差させるこずができたす。これは黒い魔法です。

やっおみたしょう



基瀎ずしお倚察倚を取りたしょう。



したがっお、3皮類の゚ンティティ



LeftEntity

RightEntity

LeftRight接続を敎理するため



LeftRightを合成キヌで䜜成したす。この゚ンティティに盎接アクセスする必芁はありたせん。倖郚から参照する必芁がないため、䞍芁なフィヌルドやむンデックスを䜜成したせん。



ク゚リの結果ずしお、巊偎の゚ンティティず右偎の゚ンティティを含むタプルのセットを取埗したいず思いたす。さらに、バヌゞン゚ンティティが正しい゚ンティティずは䜕の関係もない堎合、正しいオブゞェクトはnullになりたす。同じこずが右偎の゚ンティティにも圓おはたりたす。



LeftRightは出力ずしおは適しおいないこずが刀明したした。その制限により、゚ンティティの1぀がないずバンドルを䜜成できたせん。 DDDを緎習するず、矛盟が発生したす。

緎習しなくおも、緎習すべきではありたせん。

LeftRightFull出力の新しいタむプを䜜成したしょう。これには、巊右の゚ンティティぞのリンクが含たれおいたす。



だから、我々は



å·Š

L1

L2



右

R1

R2



LeftRight

L2 R2を



私たちは、出力で欲しい

L1 N

L2 R2

nR1



巊偎の接続から始めたしょう



var query = ctx.LeftEntities
    .SelectMany(x => x.RightLinks.DefaultIfEmpty(), (l, lr) => new LeftRightFull
    {
        LeftEntity = l,
        RightEntity = lr.RightEntity
    })




今、私たちはすでに

L1 n

L2 R2を持っおいたす



次は䜕ですか SelectManyを介しおRightEntityをスティックしたすかさお、

L1 n R1 n

L1 n R2 L2

L2 R2 R1 n

L2 R2 R2 L2を取埗



したす。条件によっお䞍芁なものL2 R2 R1nおよびL1n R2 L2を陀倖できたすが、L1 n R1nを倉換する方法は䞍明です。 in

L1 n

n R1



おそらく、発掘によっお私たちは間違った階段に連れお行かれたした。これらの同様のク゚リを、Unionを介しお巊右の゚ンティティの巊結合に接続しおみたしょう。

L1 n

L2 R2

UNION

L2 R2

nR1



ここでパフォヌマンスに぀いお質問があるかもしれたせん。すべおが特定のDBMSずそのオプティマむザの现心さに䟝存するため、私はそれらに答えたせん。



たたは、目的のク゚リを䜿甚しおビュヌを䜜成するこずもできたす。UnionはEFCore 2で動䜜しないため、ビュヌを䜜成する必芁がありたした。ただし、忘れないこずをお勧めしたす。突然、IsDeletedフラグを䜿甚しお゚ンティティの゜フト削陀を実装するこずにしたした。ビュヌでは、これをサポヌトする必芁がありたす。忘れおしたった堎合、い぀バグレポヌトを受け取るかはわかりたせん。



ちなみに、コヌド党䜓を曞き盎さずに゜フト削陀を実装するにはどうすればよいですか次回はこれに぀いおお話したす。倚分䜕か他のもの。



みなさん、さようなら。



All Articles