C# 在单独的程序集中启用带有上下文的迁移?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18126711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 11:22:58  来源:igfitidea点击:

Enable Migrations with Context in Separate Assembly?

c#.netentity-frameworkasp.net-mvc-4ef-migrations

提问by Jon

I have one project that I want to run my update-databaseagainst but I have my Models and Context in a separate project.

我有一个要运行的项目,update-database但我的模型和上下文在一个单独的项目中。

If I run enable-migrationsI get this error: No context type was found in the assembly 'MyProject'.

如果我运行,enable-migrations我会收到此错误:在程序集“MyProject”中找不到上下文类型。

This is presumably because my Context is in MyProject.MVC.

这大概是因为我的上下文在 MyProject.MVC 中。

If I run enable-migrationsagainst MyProject.MVC I have to add an app config file. I don't want to do that as I want to use the code across many projects.

如果我enable-migrations针对 MyProject.MVC运行,我必须添加一个应用程序配置文件。我不想这样做,因为我想在许多项目中使用代码。

So can I run enable-migrationsagainst MyProject and somehow tell it to look in MyProject.MVC for the Context?

那么我可以enable-migrations针对 MyProject运行并以某种方式告诉它在 MyProject.MVC 中查找上下文吗?

回答by SOfanatic

This will only work in EF 6, but there was a releasethat added the -ContextProjectNameparameter to the -enable-migrationscommand. By using this command you could do the following:

这仅适用于 EF 6,但有一个版本-ContextProjectName参数添加到-enable-migrations命令中。通过使用此命令,您可以执行以下操作:

enable-migrations -ContextProjectName MyProject.MVC -StartUpProjectName MyProject.MVC 
-ContextTypeName MyProject.MVC.MyContextFolder.MyContextName -ProjectName MyProject

This will add migrations to your MyProjectproject using the context in the MyProject.MVC. You need to make sure that the project with the Migrations has a reference to the project with your Context, i.e., MyProjectreferences MyProject.MVC

这将MyProject使用MyProject.MVC. 您需要确保具有迁移的项目具有对具有您的上下文的项目的引用,即MyProject引用MyProject.MVC

回答by Hannish

I had the same problem, and I'm using EntityFramework 4.3.1. It seems that EF6 solves this issue (according to the answer by @SOfanatic) but I didn't want to upgrade to EF6 because of some breaking changes (in the DataAnnotations, for example).

我遇到了同样的问题,我使用的是 EntityFramework 4.3.1。EF6 似乎解决了这个问题(根据@SOfanatic 的回答),但我不想升级到 EF6,因为有一些重大更改(例如在 DataAnnotations 中)。

So, what I did to solve this (and what I learned in the process):

所以,我做了什么来解决这个问题(以及我在这个过程中学到的东西):

  1. Create a new solution (empty project) and add the project where you have the model you want to enable migrations for (in your case MyProject.MVC). You may need to install the required NuGet packages for it before you are able to add the existing project.

  2. Add a config file with a connection string (don't worry, this is only to trick the migrations engine). Copy your existing database to the model project output folder (should be MVC\bin\Debug in your case). Make sure the connection string in the config file points to that database:

    <connectionStrings>
        <add name="MyDB" providerName="System.Data.SqlServerCe.4.0" connectionString="DataSource=|DataDirectory|\MyDB.sdf"/>
      </connectionStrings>
    
  3. Since you are in a new solution, set your model project as a startup project (you can remove the default project).

  4. Run the enable-migrations command in the package manager console. It should create a Migrations folder with two files: a Configuration.cs and a timestamped InitialCreate.cs file. It's nice to have the InitialCreate, that's why you put your existing database in the model project's output folder (but this is optional).

  5. Reload your original solution so that these changes are updated.

  1. 创建一个新的解决方案(空项目)并添加您想要为其启用迁移的模型的项目(在您的情况下为 MyProject.MVC)。您可能需要为其安装所需的 NuGet 包,然后才能添加现有项目。

  2. 添加一个带有连接字符串的配置文件(别担心,这只是为了欺骗迁移引擎)。将您现有的数据库复制到模型项目输出文件夹(在您的情况下应该是 MVC\bin\Debug)。确保配置文件中的连接字符串指向该数据库:

    <connectionStrings>
        <add name="MyDB" providerName="System.Data.SqlServerCe.4.0" connectionString="DataSource=|DataDirectory|\MyDB.sdf"/>
      </connectionStrings>
    
  3. 由于您在一个新的解决方案中,请将您的模型项目设置为启动项目(您可以删除默认项目)。

  4. 在包管理器控制台中运行 enable-migrations 命令。它应该创建一个包含两个文件的 Migrations 文件夹:一个 Configuration.cs 和一个带时间戳的 InitialCreate.cs 文件。拥有 InitialCreate 很好,这就是您将现有数据库放在模型项目的输出文件夹中的原因(但这是可选的)。

  5. 重新加载您的原始解决方案,以便更新这些更改。

What I learned (as far as I understand):

我学到了什么(据我所知):

  1. The migrations engine needs something that looks like a valid connection to work. I was creating my connection string in code (in another project) and that didn't work. I just gave the Migrations engine a "valid" connection string to make it work.
  2. Put your database where the migrations engine can find it (aka model project's output folder) so it creates a starting point for migrations. This starting point is basically your database schema written in the migrations API.
  3. You can restore everything to your previous state once the migrations are set in place, and it works ok.
  4. Everytime you want to manually add a migration, you must "trick" the migrations engine again, just like the first time. I haven't tried with automatic migrations, by I guess this approach works as well.
  1. 迁移引擎需要看起来像有效连接的东西才能工作。我在代码中(在另一个项目中)创建了我的连接字符串,但没有用。我只是给了 Migrations 引擎一个“有效”的连接字符串以使其工作。
  2. 将您的数据库放在迁移引擎可以找到它的地方(又名模型项目的输出文件夹),以便为迁移创建一个起点。这个起点基本上是您在迁移 API 中编写的数据库架构。
  3. 一旦迁移设置到位,您可以将所有内容恢复到以前的状态,并且它可以正常工作。
  4. 每次要手动添加迁移时,都必须再次“欺骗”迁移引擎,就像第一次一样。我还没有尝试过自动迁移,我猜这种方法也有效。

By th way, I am using a SQL Server CE 4.0 database, so some things about the connection string have a little twist compared to a standard SQL Server DB or LocalDB. Besides that, everything's the same.

顺便说一下,我使用的是 SQL Server CE 4.0 数据库,因此与标准 SQL Server DB 或 LocalDB 相比,连接字符串的某些方面有些不同。除此之外,一切都一样。

Hope this is helpful and gives you some insight. Please comment if you know more about the way this migrations work.

希望这对您有所帮助,并为您提供一些见解。如果您更了解此迁移的工作方式,请发表评论。

回答by cronixis

You may only run "Enable-Migrations" in the project containing the Database Context class.

您只能在包含 Database Context 类的项目中运行“Enable-Migrations”。

Your solution will contain 2 projects:

您的解决方案将包含 2 个项目:

1) MyProject.Models
    |- Migrations
        |- 201401061557314_InitialCreate.cs
        |- Configuration.cs
    |- MyContext.cs
    |- App.config (no connection string)


App.config


应用配置

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>



2) MyProject.MVC
        |- Filters
            |- InitializeSimpleMembershipAttribute.cs



InitializeSimpleMembershipAttribute.cs

InitializeSimpleMembershipAttribute.cs

namespace MyProject.MVC.Filters
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
    {
        private static SimpleMembershipInitializer _initializer;
        private static object _initializerLock = new object();
        private static bool _isInitialized;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Ensure ASP.NET Simple Membership is initialized only once per app start
            LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
        }

        private class SimpleMembershipInitializer
        {
            public SimpleMembershipInitializer()
            {
                try
                {
                    Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext, MyProject.Model.Migrations.Configuration>());

                    using (var context = new MyContext())
                    {
                        context.Database.Initialize(force: true);
                        if (!context.Database.Exists())
                        {
                            // Create the SimpleMembership database without Entity Framework migration schema
                            ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                        }
                    }

                    WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
                }
            }
        }
    }
}

Set MyProject.MVC as startup project

将 MyProject.MVC 设置为启动项目

In package manager, select project: MyProject.Models

在包管理器中,选择项目:MyProject.Models

Then run "Enable-Migrations" to create "Migrations" folder in MyProject.Models

然后运行“Enable-Migrations”在 MyProject.Models 中创建“Migrations”文件夹

Followed by "Update-Database" -> migrations will use connection string in Web.config from startup project to perform migration

接着是“Update-Database”->migrations 将使用启动项目中 Web.config 中的连接字符串来执行迁移

回答by Jan Bizub

Here is a workaround:

这是一个解决方法:

Add a class into MyProject(the project for migrations). Make this class inherit the dbcontext(the one in MyProject.MVC).

在 MyProject(迁移项目)中添加一个类。使这个类继承 dbcontext(MyProject.MVC 中的那个)。

Then run EF migration commands on MyProject.

然后在 MyProject 上运行 EF 迁移命令。