首页 文章

使用ASP.NET Core的Code First Entity Framework:初始迁移似乎期望表已经存在

提问于
浏览
0

我'm trying to create a Code First Entity Framework ASP.NET Core 2 project in Visual Studio Code. I'一直在关注Create a Web API with ASP.NET Core MVC and Visual Studio Code on Linux, macOS, and Windows教程,该教程使用内存数据存储作为 DbContext . 我正在尝试将其移至LocalDB .

教程Getting Started with EF Core on ASP.NET Core with a New database建议我应该能够通过迁移来完成此操作 .

获得模型后,可以使用迁移来创建数据库 . 打开PMC:工具 - > NuGet包管理器 - >包管理器控制台运行添加迁移InitialCreate以支持迁移以创建模型的初始表集 . 如果收到错误,指出“添加 - 迁移”一词未被识别为cmdlet的名称,请关闭并重新打开Visual Studio . 运行Update-Database以将新迁移应用于数据库 . 此命令在应用迁移之前创建数据库 .

VS Code相当于使用Package Manager控制台seems to be

dotnet ef migrations add InitialCreate

added EF's Design namespace with ......

dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet restore

并在我的csproj中有参考:

<ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.1" />
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>

但是当我在之后尝试 dotnet ef migrations add 命令时,它就像数据库中的TodoItems模型 needed to already exist 的表一样 . 据我所知,迁移会根据我的模型创建表格 .

c:\Projects\TodoApi>dotnet ef migrations add InitialCreate -v
Using project 'c:\Projects\TodoApi\TodoApi.csproj'.
Using startup project 'c:\Projects\TodoApi\TodoApi.csproj'.
Writing 'c:\Projects\TodoApi\obj\TodoApi.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\UserName\AppData\Local\Temp\tmp945E.tmp /verbosity:quiet /nologo c:\Projects\TodoApi\TodoApi.csproj
Writing 'c:\Projects\TodoApi\obj\TodoApi.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\UserName\AppData\Local\Temp\tmp96FF.tmp /verbosity:quiet /nologo c:\Projects\TodoApi\TodoApi.csproj
dotnet build c:\Projects\TodoApi\TodoApi.csproj /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.29
dotnet exec --depsfile c:\Projects\TodoApi\bin\Debug\netcoreapp2.0\TodoApi.deps.json --additionalprobingpath C:\Users\UserName\.nuget\packages --additionalprobingpath "C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback" --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig c:\Projects\TodoApi\bin\Debug\netcoreapp2.0\TodoApi.runtimeconfig.json C:\Users\UserName\.nuget\packages\microsoft.entityframeworkcore.tools.dotnet\2.0.0\tools\netcoreapp2.0\ef.dll migrations add InitialCreate --assembly c:\Projects\TodoApi\bin\Debug\netcoreapp2.0\TodoApi.dll --startup-assembly c:\Projects\TodoApi\bin\Debug\netcoreapp2.0\TodoApi.dll --project-dir c:\Projects\TodoApi\ --verbose --root-namespace TodoApi
Using assembly 'TodoApi'.
Using startup assembly 'TodoApi'.
Using application base 'c:\Projects\TodoApi\bin\Debug\netcoreapp2.0'.
Using working directory 'c:\Projects\TodoApi'.
Using root namespace 'TodoApi'.
Using project directory 'c:\Projects\TodoApi\'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding BuildWebHost method...
Using environment 'Development'.
Using application service provider from BuildWebHost method on 'Program'.
Found DbContext 'DatabaseContext'.
Finding DbContext classes in the project...
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT CASE
          WHEN EXISTS (
              SELECT 1
              FROM [TodoItems] AS [t])
          THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
      END
System.Data.SqlClient.SqlException (0x80131904): Invalid object name 'TodoItems'.

需要做些什么才能确保根据我的模型创建表格?

我能想到的唯一问题是我有连接字符串内联而不是appsettings.json,但我不确定为什么这是一个大问题,除非迁移正在查找默认配置 .

public void ConfigureServices(IServiceCollection services)
{
    // In memory: services.AddDbContext<DatabaseContext>(opt => opt.UseInMemoryDatabase("TodoList")); // <<< REMOVED
    string strCxn = "Server=(localdb)\\mssqllocaldb;Database=Contacts;Trusted_Connection=True;MultipleActiveResultSets=true"; // <<< ADDED

    services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(strCxn)); // <<< ADDED
    services.AddMvc();
}

Fwiw,这些是我对TodoApi教程代码中从内存数据库迁移到LocalDB的唯一变化 .


Update: Fwiw,我尝试更改连接字符串中的数据库名称..

string strCxn = "Server=(localdb)\\mssqllocaldb;Database=Contacts2;Trusted_Connection=True;MultipleActiveResultSets=true";

(将 Contacts 更改为 Contacts2 ,以防它认为,因为它最初找到了联系人数据库,已经进行了迁移...)

这也没有用,虽然错误改变的方式表明连接字符串正在工作并被读取 .

Cannot open database "Contacts2" requested by the login. The login failed.
Login failed for user 'COMPUTER-NAME\UserName'.

1 回答

  • 0

    作为 DbContext 构造函数的一部分,我正在播种数据......

    public class DatabaseContext : DbContext    {
        public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
        {
            this.MinimallySeedDatabase();
        }
    
        public void MinimallySeedDatabase()
        {
            State NY = this.States.Where(s => s.Abbr.Equals("NY")).FirstOrDefault();
            if (null == NY)
            {
                NY = new State {
                    Name = "New York",
                    Abbr = "NY"
                };
                this.States.Add(NY);
                this.SaveChanges();
            }
    
            // etc etc etc...
        }
    
        public DbSet<Contact> Contacts {get; set;}
        public DbSet<Address> Addresses {get; set;}
        public DbSet<AddyType> AddyTypes {get; set;}
        public DbSet<State> States {get; set;}
    }
    

    部分迁移的执行涉及在迁移 DbSet 的表之前显式实例化 DbContext . 由于构造函数(在此示例中)需要访问状态,并且由于迁移还没有创建状态表,因此迁移会爆炸 .

    如果我拿出播种,我很好 . 如果你想种子,你需要移动到构造函数之外的其他地方,即使构造函数中的种子在迁移尝试之外/在正常的Kestrel测试中工作正常 .

    对我来说,当我运行迁移时,我只是注释掉了 this.MinimallySeedDatabase(); .

相关问题