web-dev-qa-db-ja.com

クラスライブラリプロジェクトのEntity Framework Core移行の使用

これは すでに修正された問題 のようです。少なくともSQLiteデータベースについては。

私のソリューションは3つのプロジェクトで構成されています。

  1. WPFプロジェクト(デフォルトのスタートアッププロジェクト)(。NET Framework 4.7)、
  2. ビューモデルと非UIスタッフを保持する「コア」プロジェクト-クラスライブラリプロジェクト(。NET Standard 2.0
  3. すべてのEntity Frameworkデータレイヤーを保持する「リレーショナル」プロジェクト-それらを分離しておくのが好きです(。NET Standard 2.0

次のパッケージをメインのWPFプロジェクトにインストールしました。

Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design

プロジェクト2と3は、メインのWPFプロジェクトで参照されています。基本的に、EFがDbContextesを解決するのに十分なはずです。

ただし、そうではありません-Add-Migration私のWPFプロジェクトの結果:

PM> Add-Migration "Initial"
No DbContext was found in Assembly 'TestWPFProject'. Ensure that you're using the correct Assembly and that the type is neither abstract nor generic.

プロジェクトへの切り替え3パッケージマネージャーコンソールのデフォルトとして次のようになります。

PM> Add-Migration "Initial"
Unable to create an object of type 'ClientDbContext'. Add an implementation of 'IDesignTimeDbContextFactory<ClientDataStoreDbContext>' to the project, or see https://go.Microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.

クラスライブラリプロジェクトとWPFプロジェクトでEF Core移行を適切に使用するにはどうすればよいですか?

11
Lucas

私はあなたの解決策を再現し、解決策を見つけました... :)

  1. 「コア」プロジェクト-ClassLibrary1と呼ばれる
  2. 「リレーショナル」プロジェクト-EFClssLibraryと呼ばれる
  3. WPF Appプロジェクト-WpfApp1と呼ばれる

深めましょう。


1.コアプロジェクト

名前ClassLibrary1

タイプ。NET Standard 2.0クラスライブラリ

依存関係:なし。

私のテストソリューションでは、Personと呼ばれるモデルという1つのクラスのみが含まれています。

Person.cs

namespace ClassLibrary1
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
    }
}

2.関係プロジェクト

名前EFClassLibrary

タイプ。NET Standard 2.0クラスライブラリ

依存関係

私のテストソリューションのこのプロジェクトには、データベースコンテキストというクラスが1つだけ含まれています。

ClientDbContext.cs

using ClassLibrary1;
using Microsoft.EntityFrameworkCore;

namespace EFClassLibrary
{
    public class ClientDbContext : DbContext
    {
        const string connectionString = "Server=(localdb)\\mssqllocaldb;Database=ClientDb;Trusted_Connection=True;";

        public ClientDbContext() : base() { }

        public ClientDbContext(DbContextOptions<ClientDbContext> options) : base(options) { }

        public DbSet<Person> People { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(connectionString);
        }
    }
}

接続文字列

このクラスでは、データベースに接続するために接続文字列を使用して定義しました(LocalDb SQL Serverと仮定)。接続文字列を設定ファイルに入れたい場合は、共有設定ファイルをソリューションに追加してから、そのファイルをApp.configファイル(詳細については このページ をご覧ください)

ターゲットフレームワークの構成

スタートアッププロジェクトとして他のプロジェクトを設定せずにこのプロジェクトに移行を追加できるようにするには、ターゲットフレームワークを設定する必要があります。プロジェクトを右クリックして、Edit EFClassLibrary.csprojエントリをクリックします。 <TargetFramework>netstandard2.0</TargetFramework>行、ターゲットにするフレームワークを指定する別の行を追加する必要があります。 .NET Framework 4.7をターゲットにするには、追加する必要があります

<TargetFramework>net47</TargetFramework>

許可されるすべての値のリストは、 here にあります。

私のEFClassLibrary.csprojは、.NET Framework 4.7をターゲットとして追加すると、次のコードのようになります。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <TargetFramework>net47</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" />
  </ItemGroup>

</Project>

移行を追加する

これで、最初の移行を追加する準備ができました。パッケージマネージャーコンソールを開き、デフォルトプロジェクトとしてEFClassLibraryを設定します。また、そのプロジェクトをスタートアッププロジェクトとして設定します(プロジェクトを右クリックして、スタートアッププロジェクトとして設定エントリをクリックします)。

タイプ

PM> Add-Migration Initial

それから

PM> Update-Database

3. WPFアプリプロジェクト

名前WpfApp1

タイプWPF Applicationusing。NET Framework 4.7

依存関係

このプロジェクトでは、ファイルを追加しませんでした。編集したMainWindow.xaml.csファイルを使用して、すべてが正しく機能することを確認します。

MainWindow.xaml.cs

using ClassLibrary1;
using EFClassLibrary;
using System.Windows;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var db = new ClientDbContext();

            db.People.Add(new Person()
            {
                Name = "Omar"
            });

            db.SaveChanges();
        }
    }
}

それが役に立てば幸い :)

17
OmarMuscatello

私のために働いたのは、UI Side Startup.csで通常のことをするだけです

services.AddDbContext<ShentonEvaDbContext>(options =>
                options.UseSqlServer(
                    _configuration.GetConnectionString("DevelopmentConnection")));

次に、DBContext設定でコンストラクタを追加するだけです

public ShentonEvaDbContext(DbContextOptions<ShentonEvaDbContext> options) : base(options)
        {

        }

その後、パッケージマネージャーコンソールで次を実行します。

dotnet ef migrations add InitialMigration --project "NameOfDbContextProject" --startup-project "NameOfWebUIProject"

それからEverytihngが追加され、データベースの更新についても同じことが行われました

6

スタートアッププロジェクトでは、IDesignTimeDbContextFactoryを実装するファクトリを作成し、DBContextを作成する必要があります。

public class DBContextFactory : IDesignTimeDbContextFactory<DBContext>
        {
            public DBContext CreateDbContext(string[] args)
            {
                var optionsBuilder = new DbContextOptionsBuilder<DBContext>();

                // Row numbers for paging adds support for old SQL server 2005+. See more: 
                // https://docs.Microsoft.com/en-us/ef/core/api/Microsoft.entityframeworkcore.infrastructure.sqlserverdbcontextoptionsbuilder
                optionsBuilder.UseSqlServer("Server=localhost;Database=DatabaseName;Trusted_Connection=True;MultipleActiveResultSets=true;Integrated Security=SSPI", x => x.UseRowNumberForPaging());

                return new DBContext(optionsBuilder.Options);
            }
        }
3
Gaurav Jalan

Microsoft は、移行用の新しいクラスライブラリを作成し、モデルスナップショットファイルと移行を新しいクラスライブラリに移動することを提案しています。

追加していない場合は、DbContextプロジェクトに追加してから移動します。

次に、移行アセンブリを構成します。

options.UseSqlServer(
    connectionString,
    x => x.MigrationsAssembly("MyApp.Migrations"));

次に、スタートアップアセンブリから移行アセンブリへの参照を追加します。

注:

これにより循環依存が発生する場合は、クラスライブラリの出力パスを更新します:

<PropertyGroup>
  <OutputPath>..\MyStarupProject\bin\$(Configuration)\</OutputPath>
</PropertyGroup>

2番目の参照として、クラスライブラリプロジェクトのEntityFramework Core移行に関するガイド Ben Cull's を使用します。

3
Barr J

クラスライブラリプロジェクトをデータレイヤーとして使用し、asp.netコアプロジェクトをスタートアッププロジェクトとして使用していました。最初に、asp.netスタートアップクラスにE.Fコアコンテキストを登録しました。

public void ConfigureServices(IServiceCollection services)
{
     //DataLayer namespace is in class library project
     services.AddDbContext<DataLayer.EFCoreContext>();
}

次に、(クラスライブラリプロジェクトにある)コンテキストクラスで、設定ファイルから接続文字列を提供し、OnConfiguringメソッドで使用しました。

public class EFCoreContext: DbContext
{
        private string ConnectionString { get; set; }
        public EFCoreContext() : base()
        { 
            var settingsPath= AppDomain.CurrentDomain.BaseDirectory;
            settingsPath +=  @"\datalayersettings.json";
            var datalayersettings =File.ReadAllText(settingsPath);
            dynamic jSetting = JObject.Parse(datalayersettings);
            this.ConnectionString = 
                    (string)jSetting.ConnectionStrings.ConnectionString;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder 
                                              optionsBuilder)
        {
            optionsBuilder.UseSqlServer(this.ConnectionString);
        }
}

次に、移行の適用とデータベースの更新のために、それぞれ次のコマンドを使用しました

add-migration MyEFCoreMigration -Context DataLayer.EFCoreContext -Project DataLayer

Update-Database -Context DataLayer.EFCoreContext -Project DataLayer
0