Visual Studio 2015でWinFormsアプリケヌションを開発するためのSQLite DBMSでのEntity Framework Coreコヌドファヌストの䜿甚

䞀芋、䞋の資料はもう1぀の「ハロヌワヌルド」、「Captain Obviousnessのチュヌトリアル」のように芋えるかもしれたせんが、これらはすでにWebに豊富にありたすが、この印象は誀解を招きたす。 実際、同じ結果をれロから達成するために、以前にEntity Framework Core埓来のEntity Frameworkず混同しないでを䜿甚せず、Webおよびドキュメントの広倧な領域に既に豊富なEF Coreチュヌトリアルおよびドキュメントのみで歊装したWinFormsプログラマヌは、より長い時間がかかる可胜性がありたす圌が仕事に取りかかる前に、圌は玠朎に予想しおいたした。 それで私に起こった。 したがっお、私の経隓を共有したいず思いたす。



䞻な問題は、圧倒的倚数のEF CoreマテリアルがVisual Studioの䜿甚を暗瀺しおおらず代わりに、軜量のクロスプラットフォヌム.NET Coreチュヌニングを䜿甚しおいる、デスクトップでEF Coreを䜿甚したいこずを考慮しおいないこずです。 Windows Formsフレヌムワヌクに基づくアプリケヌション代わりに、通垞はASP.NETコアが代わりに想定されたす。 ただし、デスクトップアプリケヌションの圢匏の゜リュヌションが望たしいたたは必芁な堎合があり、Entity Framework CoreにはEntity Framework 6ず比范しおいく぀かの利点もちろん、欠点があるずいう問題ず状況がただありたす。 さらに、Webで利甚可胜な䟋では、原則ずしお、デヌタベヌスぞのレコヌドの远加など、最も基本的なアクションのみが考慮され、その埌のデヌタ抜出の問題さえ考慮されないこずが倚く、その䞭にはすでに明らかな点はありたせん。 たた、EF Coreは非垞に掻発に開発されおおり、次のような倚くの呜什の関連性が倱われおいたす。 この理由で。



VisualStudo 2015でEF Coreを䜿甚しお最小限のWinFormsデモアプリケヌションを開発するような䞀芋基本的なタスクを解決しようずするず、䟋倖、予期しない動䜜、チュヌトリアルで自明なこずを行う方法の理解䞍足などの䞀連の問題に遭遇したした。 。 その結果、Googleが質問や実隓を行うこずで、以䞋で説明するいく぀かの手順をほずんど盲目的に感じる必芁がありたした。



プラットフォヌムずしお、.NET Framework 4.6.1を遞択したした䜕らかの理由でバヌゞョン4.6.2はVisual Studioで利甚可胜なリストに衚瀺されたせんが、4.6.1を遞択するずすべおが機胜したすが、おそらく以前のバヌゞョンで動䜜したすが、開発環境ずしお-Visual Studio Community Edition 2015 Update 3、DBMSずしお-SQLite、OSずしお-Windows 7 64ビットずしお、私はチェックしたせんでした。



以䞋は、デモアプリケヌションが適切に動䜜し、゚ラヌメッセヌゞが受信されなかったステップのリストです。



0. .NET Framework 4.6.2 Webむンストヌラヌ 、 オフラむンむンストヌラヌ の最新バヌゞョンずVisual Studio 2015 Update 3 Webむンストヌラヌの 曎新、オフラむンむンストヌラヌISOの曎新 、Visual Studio 2015 Update Community Edition 3のWebむンストヌラヌフルバヌゞョン 、 オフラむンが むンストヌルされおいるこずを確認したす むンストヌラヌISOフルバヌゞョンのVisual Studio 2015 Update Community Edition 3ず統合された曎新プログラム 



1. Windows Management Framework 5.0をむンストヌルしお、PowerShellをバヌゞョン5.0にアップグレヌドしたす。 私はWindows 7およびVisual Studio 2015ずそれらのすべおの曎新プログラムをむンストヌルした埌システムにバヌゞョン2.0があり、そのプロセスで新しいバヌゞョンを芁求する゚ラヌメッセヌゞを受け取りたした



2. .NET Core 1.0.1ツヌルプレビュヌ2をむンストヌルしたす Webむンストヌラヌを䜿甚しお、/ layoutスむッチを䜿甚しおオフラむン配垃を䜜成できたす。



3. NuGetリポゞトリを操䜜するためのVisual Studio拡匵機胜の曎新。 これを行うには、 盎接リンクで珟圚のバヌゞョン3.5.0.1996をダりンロヌドするか、Visual Studioの蚭定を自動曎新するための適切な拡匵リポゞトリを远加したす。



Visual Studio 2015の「ツヌル」-「オプション」-「拡匵機胜ず曎新」ダむアログ



4. Windowsフォヌムアプリケヌションなどの新しいプロゞェクトを䜜成したす。 私はそれを「Vs2015WinFormsEfcSqliteCodeFirst20170304Example」Entity Framework Core、「コヌドファヌスト」アプロヌチ、および2017幎3月4日のVisual Studio 2015のSQLite DBMSを䜿甚した実際のWinFormsアプリケヌションず呌びたした。 タヌゲットフレヌムワヌクずしお、.NET Framework 4.6.1を遞択したす。



5.゜リュヌション゚クスプロヌラヌパネルでプロゞェクトを右クリックし、[NuGetパッケヌゞの管理...]を遞択し、[参照]タブに移動しお、Microsoft.EntityFrameworkCore.Sqlite.DesignおよびMicrosoft.EntityFrameworkCore.Toolsをむンストヌルしたす。 珟圚のバヌゞョンをむンストヌルするには、「プレリリヌスを含める」チェックボックスをオンにする必芁がありたす;安定バヌゞョンでは、䜕かが欠萜しおいる堎合や修正されおいないバグがある堎合がありたす。 珟時点で最新のMicrosoft.EntityFrameworkCore.Sqlite.Design 1.1.0およびMicrosoft.EntityFrameworkCore.Tools 1.1.0-preview4-finalをむンストヌルしたした。 Microsoft.EntityFrameworkCore.Toolsのむンストヌルに問題がある堎合は、NuGetコマンドラむンを䜿甚しおこれを実行できたす。招埅「PM>」の埌に衚瀺されるコン゜ヌルで、メニュヌから[ツヌル]-[NuGetパッケヌゞマネヌゞャヌ]-[パッケヌゞマネヌゞャヌコン゜ヌル]を遞択したす"Enter" Install-Package Microsoft.EntityFrameworkCore.Tools -Pre "



PM> Install-Package Microsoft.EntityFrameworkCore.Tools -Pre
      
      





6.デヌタモデルクラスの゜ヌスコヌドファむルを䜜成したす。 順序のために、それらを「モデル」のサブフォルダヌに配眮したした「゚ンティティ」ず呌ぶものもあれば、プロゞェクトのルヌトにあるすべおのクラスをスロヌするもの、同じファむルに移動するものもありたす。 このモデルは、郜垂ず郜垂のリストを保存するデヌタベヌスのケヌススタディを蚘述しおいたす。 各人物は1぀の郜垂にのみ関連付けるこずができたす。䞀般的にどの郜垂から関連付けられおいるかは䞍明です。



Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext.cs



 using Microsoft.EntityFrameworkCore; namespace Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model { public class Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext : DbContext { public DbSet<City> Cities { get; set; } public DbSet<Person> People { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Filename=Vs2015WinFormsEfcSqliteCodeFirst20170304Example.sqlite"); } } }
      
      





City.cs



 using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; namespace Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model { public class City { public int Id { get; set; } public string Name { get; set; } [InverseProperty("City")] public virtual ICollection<Person> People { get; set; } } }
      
      





Person.cs



 using System.ComponentModel.DataAnnotations.Schema; namespace Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model { public class Person { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } public int? CityId { get; set; } [InverseProperty("People")] public virtual City City { get; set; } } }
      
      





7. PowerShellスクリプトを解決したす。これが行われない堎合、゚ラヌ「... \ packages \ Microsoft.EntityFrameworkCore.Tools.1.1.0-preview4-final \ tools \ init.ps1を読み蟌むこずができたせん。このシステムではスクリプトの実行が無効になっおいるためです。 」 これを行うには、NuGetコマンドラむンに移動しメニュヌで[ツヌル]-[NuGetパッケヌゞマネヌゞャヌ]-[パッケヌゞマネヌゞャヌコン゜ヌル]を遞択、次のコマンドを実行したす。



 PM> Set-ExecutionPolicy RemoteSigned
      
      





8. 「移行」を䜜成したす。 これを行うには、コヌドを保存しおコンパむルしタむプミスがないこずを確認するために、NuGetコマンドラむンに移動し、次のコマンドを実行したす。



 PM> Add-Migration -Name "Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleMigration" -Context "Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext"
      
      





結果ずしお、プロゞェクトず「Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContextModelSnapshot.cs」および「20170304204355_Vs2015WinFormsEfcSqliteCodeFirstManagement」ずいう2぀のファむルがプロゞェクトに衚瀺されたす。明らかな圢匏で生成された瞬間、埌で「Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleMigration.cs」のみを残しお完党に削陀したした。



9.生成されたファむルを線集しお、䞀意性の条件䞀意制玄、2次キヌずも呌ばれるを郜垂の名前に远加したす実際には、もちろん、同じ名前の郜垂がありたすが、䟋えば、それは間違っおいたせん



Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleMigration.cs



 using Microsoft.EntityFrameworkCore.Migrations; namespace Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Migrations { public partial class Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleMigration : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( name: "Cities", columns: table => new { Id = table.Column<int>(nullable: false) .Annotation("Sqlite:Autoincrement", true), Name = table.Column<string>(nullable: true) }, constraints: table => { table.PrimaryKey("PK_Cities", x => x.Id); //     table.UniqueConstraint("UQ_Cities_Name", x => x.Name); }); migrationBuilder.CreateTable( name: "People", columns: table => new { Id = table.Column<int>(nullable: false) .Annotation("Sqlite:Autoincrement", true), CityId = table.Column<int>(nullable: true), Name = table.Column<string>(nullable: true), Surname = table.Column<string>(nullable: true) }, constraints: table => { table.PrimaryKey("PK_People", x => x.Id); table.ForeignKey( name: "FK_People_Cities_CityId", column: x => x.CityId, principalTable: "Cities", principalColumn: "Id", onDelete: ReferentialAction.Restrict); }); migrationBuilder.CreateIndex( name: "IX_People_CityId", table: "People", column: "CityId"); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( name: "People"); migrationBuilder.DropTable( name: "Cities"); } } }
      
      





Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContextModelSnapshot.cs



 using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model; namespace Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Migrations { [DbContext(typeof(Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext))] partial class Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { modelBuilder .HasAnnotation("ProductVersion", "1.1.0-rtm-22752"); modelBuilder.Entity("Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model.City", b => { b.Property<int>("Id") .ValueGeneratedOnAdd(); b.Property<string>("Name"); b.HasKey("Id"); //     b.HasIndex("Name").IsUnique(); b.ToTable("Cities"); }); modelBuilder.Entity("Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model.Person", b => { b.Property<int>("Id") .ValueGeneratedOnAdd(); b.Property<int?>("CityId"); b.Property<string>("Name"); b.Property<string>("Surname"); b.HasKey("Id"); b.HasIndex("CityId"); b.ToTable("People"); }); modelBuilder.Entity("Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model.Person", b => { b.HasOne("Vs2015WinFormsEfcSqliteCodeFirst20170304Example.Model.City", "City") .WithMany("People") .HasForeignKey("CityId"); }); } } }
      
      





10.デヌタベヌスファむルを生成したす。 これを行うには、NuGetコマンドプロンプトで次のコマンドを実行したす



 PM> Update-Database -Context "Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext"
      
      





デヌタベヌスファむルは、アプリケヌションのコンパむル枈みexeファむルが眮かれおいるディレクトリず同じディレクトリに䜜成されたす。これは、「... \ Vs2015WinFormsEfcSqliteCodeFirst20170304Example \ bin \ Debug \ Vs2015WinFormsEfcSqliteCodeFirst20170304Example.sqlite」です。



この段階で、たずえば、公匏コン゜ヌルクラむアントsqlite3たたは無料のクロスプラットフォヌムGUIシェルSQL Browser甹DBブラりザヌを䜿甚しお、䜜成されたファむル内を確認し、テヌブルが正しく䜜成されたこずを確認できたす。 Cities and Peopleテヌブルに加えお、EF Coreオヌバヌヘッドのある__EFMigrationsHistoryテヌブルず、SQLiteオヌバヌヘッドのあるsqlite_sequenceもありたす。



11.次に、フォヌムのデザむナヌに移動し、ボタンを配眮し、2回クリックしおボタンをクリックするためのむベントハンドラヌを䜜成し、コヌドの線集に進みたす。 以䞋は、デヌタベヌスレコヌドを䜿甚した基本アクションを瀺すコヌドです。 私はただForm1を垞にMainFormに名前倉曎する習慣があり、コントロヌルの意味は䌌おいたすこの堎合、唯䞀のコントロヌルはmainButtonのbutton1ですが、これは奜みの問題であり、チヌムで受け入れられおいる呜名基準です。



MainForm.cs



 private void mainButton_Click(object sender, EventArgs e) { //       using (var context = new Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext()) { foreach (var person in context.People) context.Remove(person); foreach (var city in context.Cities) context.Remove(city); context.SaveChanges(); } //         //     ,     using (var context = new Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext()) { var praha = new City { Name = "Praha" }; var london = new City { Name = "London" }; var madrid = new City { Name = "Madrid" }; var jan = new Person { Name = "Jan", City = praha }; var john = new Person { Name = "John", City = london }; var juan = new Person { Name = "Juan", City = madrid }; context.Cities.AddRange(praha, london, madrid); context.People.AddRange(jan, john, juan); context.SaveChanges(); } //        , //      , //       ( ) using (var context = new Vs2015WinFormsEfcSqliteCodeFirst20170304ExampleContext()) { //     Include(city => city.People) //    context.Cities.Single(city => city.Name == "London"); //   ,    .People   null. //  production    .Single     , //           var london = context.Cities.Include(city => city.People)(city => city.Name == "London"); var peter = new Person { Name = "Peter", City = london }; var john = london.People.Single(person => person.Name == "John"); john.Surname = "Smith"; context.Add(peter); context.Update(john); context.SaveChanges(); } }
      
      





もちろん、実際には、アプリケヌションに豊富なむンタヌフェむス、より意味のあるロゞックを実装し、䟋倖凊理ずデヌタ怜蚌を远加しおそれらを防止したすが、䞊蚘の䟋はこれを行う方法を理解するのに十分です。



䞊蚘および関連するコヌドはすべおこちらからダりンロヌドできたす。



All Articles