I am working with my first project using Entity Framework 7 and am connecting to a SQL Server where the Database is already created but there are no tables in it yet. I have created my DbContext and created a class, then set a DbSet<> inside my context. I ran the commands to enable migrations and create the first migration, then rand the command to update the database. Everything looked to work fine, no errors came up, but when I look at the database only the EFMigraitonsHistory table was created. When I look at the class that was created for the initial migration it is essentially blank. What am I doing wrong?
Commands I am running:
dnvm install latest -r coreclr
dnx ef migrations add MyFirstMigration
dnx ef database update
Context:
namespace JobSight.DAL
{
public class JobSightDBContext : DbContext
{
public DbSet<NavigationMenu> NavigationMenu { get; set; }
}
}
Table Class:
namespace JobSight.DAL
{
public class NavigationMenu
{
[Required, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int16 ID { get; set; }
public string ControllerName { get; set; }
public string ActionName { get; set; }
public string ExternalURL { get; set; }
public string Title { get; set; }
public Int16? ParentID { get; set; }
public virtual NavigationMenu Parent { get; set; }
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<JobSightDBContext>(options =>
{
options.UseSqlServer(Configuration["Data:JobSightDatabase:ConnectionString"]);
});
}
Class for initial migration (autogenerated by EF):
namespace JobSight.WebUI.Migrations
{
public partial class Initial : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
Edit:
After doing what Poke has suggested this is my new auto-generated migration. The table is still not being created at the database level though.
namespace JobSight.WebUI.Migrations
{
public partial class MyFirstMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "NavigationMenu",
columns: table => new
{
ID = table.Column<short>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
ActionName = table.Column<string>(nullable: true),
ControllerName = table.Column<string>(nullable: true),
ExternalURL = table.Column<string>(nullable: true),
ParentID = table.Column<short>(nullable: true),
Title = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_NavigationMenu", x => x.ID);
table.ForeignKey(
name: "FK_NavigationMenu_NavigationMenu_ParentID",
column: x => x.ParentID,
principalTable: "NavigationMenu",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable("NavigationMenu");
}
}
}
You need to set up the entity in your database context first. At the very least, you would need to do this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<NavigationMenu>();
}
The problem with your migrations was a bit hidden in your project layout. So what you have is a JobSight.DAL project that contains the entities and the database context. And then you have a project JobSight.WebUI which is the actual ASP project containing the Startup.cs with the database setup.
This is causing problems because by default EF will just assume to find everything in the current assembly. So if you are launching the ef command from your web project, it will create the migrations in there even if the context is in another project. But when you’re then trying to apply the migration, EF will not find it since it will only look in the context’s project.
So to fix this, you need to create the migrations in the DAL project. You can do that by specifying the project when you call the ef command:
dnx ef migrations add Example -p JobSight.DAL
You can verify that this worked by running dnx ef migrations list afterwards. This should now return the Example migration; previously, that command didn’t return anything: It could not find a migration which is the reason why the update command only said Done (without applying the migration) and the database wasn’t created. So if you now get the migration there, you can then apply it using:
dnx ef database update
Note that since the migration is now created in the DAL project, you need to add a reference to EntityFramework.MicrosoftSqlServer there, otherwise the project will not compile. You need to do that before you can run the list command above.
Finally, for some more information about this, see this issue.
Although this is not the answer to the original question, I post my answer here because it might help someone who has a similar problem. My problem was also that the tables were not created, but dotnet ef migrations add InitialCreate did create 3 .cs files in the Migrations folder. But dotnet ef database update only created the MigrationsHistory table and dotnet ef migrations list did not return any migrations.
It turned out that the problem was that the Migrations folder was excluded from the Visual Studio project. Once I included it again, everything worked fine.
I had the same problem and this is how I resolved it
I deleted my database in SQL
I changed the name I used for the previous migration. I changed from "Add-Migration InitialCreate" to "Add-Migration NewName"
Related
ASP Core 3.1 - API. I'm using the latest version of Entity Framework Core.
I have created a table ToDoItem and a ToDoItemContext. After creating the initial migration, and running update-database. I now have that table in my database. I now added a new model called: ToDoItemDescription.
When I try to update the database after creating a new migration, I get the error:
Table 'todoitems' already exists
Further details: I have two contexts, and this is the command I ran:
update-database -context todoitemscontext
I also tried:
update-database -context todoitemscontext -migration AddDescription
Here is my full code:
Models:
public class TodoItem : IEntity
{
public long Id { get; set; }
public string Name { get; set; }
bool IsComplete { get; set; }
}
public class ToDoItemDescription
{
public int id { get; set; }
public string Description { get; set; }
//public int ToDoItemId { get; set; }
public TodoItem TodoItem { get; set; }
}
Context:
public class TodoItemsContext : DbContext
{
public TodoItemsContext(DbContextOptions<TodoItemsContext> options) : base(options) { }
public DbSet<TodoItem> TodoItems { get; set; }
public DbSet<ToDoItemDescription> TodoItemsDescription { get; set; }
}
Migrations:
[DbContext(typeof(TodoItemsContext))]
partial class TodoItemsContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder) {
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.9")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("project.Models.ToDoItemDescription", b => {
b.Property<int>("id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Description")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.Property<long?>("TodoItemId")
.HasColumnType("bigint");
b.HasKey("id");
b.HasIndex("TodoItemId");
b.ToTable("TodoItemsDescription");
});
modelBuilder.Entity("project.Models.TodoItem", b => {
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<bool>("IsComplete")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.HasColumnType("longtext CHARACTER SET utf8mb4");
b.HasKey("Id");
b.ToTable("TodoItems");
});
modelBuilder.Entity("project.Models.ToDoItemDescription", b =>
{
b.HasOne("project.Models.TodoItem", "TodoItem")
.WithMany()
.HasForeignKey("TodoItemId");
});
#pragma warning restore 612, 618
}
public partial class TodoItems_Initial : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "TodoItems",
columns: table => new
{
Id = table.Column<long>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(nullable: true),
IsComplete = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TodoItems", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "TodoItems");
}
}
public partial class AddDescription : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "TodoItemsDescription",
columns: table => new
{
id = table.Column<int>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Description = table.Column<string>(nullable: true),
TodoItemId = table.Column<long>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_TodoItemsDescription", x => x.id);
table.ForeignKey(
name: "FK_TodoItemsDescription_TodoItems_TodoItemId",
column: x => x.TodoItemId,
principalTable: "TodoItems",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_TodoItemsDescription_TodoItemId",
table: "TodoItemsDescription",
column: "TodoItemId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "TodoItemsDescription");
}
}
Thank you.
This happens if you have created the database upfront without migrations, for example by using DbContext.Database.EnsureCreated();.
This usually happens when you have a migration that creates a table and the required table is already present in your database so, when you update the database from classes in Migration, it will try to create a table and will fail because the Create command will not be executed as it already has that specific table.
So, in order to avoid the error, you might want to remove the migration class or comment the code in Up() method of that class so it doesn't execute that specific create command.
It could possible help people working with MySQL databases either on Linux and Windows
TL;DR;
I had to rename the table
__efmigrationshistory (note the lowercase) to
__EFMigrationsHistory (note the case)
so the command-line dotnet-ef database update managed to verify all the migrations present on the table __EFMigrationsHistory, and therefore, creating the new field on the table, say Tenant
More
I have to work on Linux, Windows, MacOs boxes. Primarily using Visual Studio code and .net core 3.1.xxx
I use the code-first approach. The MySQL database was firstly, create on the Windows box, where all the tables were created lower cased
Switching to the Linux box, I realized the case was important, so, say, table "tenant" was renamed to "Tenant", by hand.
Once I had to create a new field on the Tenant's c# class, I ran:
dotnet-ef migrations add new-ftpSettings-field and dotnet-ef database update, I got table "Order" already exists. Note I was trying to insert a new field to the "Tenant" table
After a lot of investigation and search, I decided to refresh the database again, and I saw "two suspicious tables" __efmigrationshistory and __EFMigrationsHistory.
I renamed the empty table __EFMigrationsHistory to like Table1 (as a backup), and thus renamed the table __efmigrationshistory to __EFMigrationsHistory
I ran the dotnet-ef database update and the field was properly added to the MySQL database.
*** Like you might have figured this out, running the command-line dotnet-ef database update on Linux was creating a new (and) empty table __EFMigrationsHistory to MySQL database while it had already, a lower cased table on __efmigrationshistory (the good one, created on my Windows box, with all the migrations).
*** This is my first contribution. Any advice is welcome!
Keep safe! Tchau/Au revoir!
I was working through the migration tutorial and had made a mistake sometimes around these steps
dotnet ef migrations add AddBlogCreatedTimestamp
dotnet ef database update
I did the following
deleted the files AddBlogCreatedTimestamp.Designer.cs and AddBlogCreatedTimestamp.cs
inside blogging.db in the table __EFMigrationsHistory i deleted the row that contains 2023__***__AddBlogCreatedTimestamp this was the migration step that failed.
I repeated the migration step dotnet ef migrations add ...
then manually added DropTable(...) to AddBlogCreatedTimestamp.Up()
only then i ran dotnet ef database update
This made sure that in an up-migration the tables would be deleted
Code manually changed
public partial class AddBlogCreatedTimestamp : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
// manually added
migrationBuilder.DropTable(name: "Posts");
migrationBuilder.DropTable(name: "Blogs");
// ... other lines that were created
}
// more other code ...
}
What i still not get is why this is needed. I am not aware to have used anything like EnsureCreated
Entity Framework is not respecting my Identity columns. It insists on trying to insert a value into an Identity (auto-increment) column in my MS SQL DB, which is obviously an error since the DB is supposed to supply the value.
System.Data.SqlClient.SqlException: 'Cannot insert explicit value for identity column in table 'Assignee' when IDENTITY_INSERT is set to OFF.'
Why is it trying to do that? I've paired it down to a schema involving one table and one column:
CREATE TABLE [dbo].[Assignee](
[AssigneeID] INT IDENTITY(-1, 1) NOT NULL
CONSTRAINT [Assignee$PrimaryKey] PRIMARY KEY CLUSTERED
( [AssigneeID] ASC ))
After publishing this schema to my local DB I use Scaffold-DbContext to generate entity and context classes. The generated Assignee class contains just this public property.
public int AssigneeId { get; set; }
The context only refers to Assignee here:
modelBuilder.Entity<Assignee>(entity =>
{
entity.Property(e => e.AssigneeId).HasColumnName("AssigneeID");
});
Searching around I see people claiming that for E.F. to respect Identity columns, the context should configure the property with ValueGeneratedOnAdd(). In other words, the line in the context class should read:
entity.Property(e => e.AssigneeId).HasColumnName("AssigneeID")
.ValueGeneratedOnAdd();
I have two problems with this:
I'm starting with an existing DB and generating entity classes. If I need ValueGeneratedOnAdd() then why isn't Scaffold-DbContext generating it?
Even if I manually edit the generated context class and add ValueGeneratedOnAdd() it still doesn't work with the same error.
Elsewhere I see suggestions to use UseSqlServerIdentityColumn(). That also doesn't work for me. Points 1 and 2 still apply.
Any help would be greatly appreciate. Please don't suggest that I use IDENTITY_INSERT as that defeats the entire point of using auto-increment columns.
(I am using Entity Framework Core 2.2.3 and Microsoft SQL Server 14)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Todo>(entity =>
{
entity.Property(x => x.Id)
.HasColumnName("id")
.HasColumnType("int")
.ValueGeneratedOnAdd()
**.UseIdentityColumn();**
}
Try do this.
Ef Core Dependency : Microsoft.EntityFrameworkCore.SqlServer
This works for me:
modelBuilder.Entity<Assignee>().Property(e => e.AssigneeId).UseIdentityColumn();
So UseIdentityColumn() is the key.
I'm using Microsoft.EntityFrameworkCore.SqlServer v3.1.8.
Short version
We are getting and experiencing different results here one can reproduce the issue, others can not. My experience it depends on if the Id property's value is 0 or not.
Detailed version
My experience, that the default behavior (based on name convention) is definitely working, so in case you are naming your db entity's attribute (C# property) to Id or EntityNameId it should work. No C# entity class attributes neither OnModelCreating config is necessary.
The same time if the issue is there neither No C# entity class attributes neither OnModelCreating config will fix it.
...because if the Id property's value is not 0, the generated SQL will contain the explicit field name and value, so we got the error.
This is clearly and issue in EF core, but workaround is easy..
For DB first try adding [key] as a data annotation
With Data annotation
[Key]
public int AssigneeId { get; set; }
fluent API
modelBuilder.Entity<Assignee>()
.HasKey(o => o.AssigneeId);
See here or here if you want to use fluent API
I've tried to reproduce this issue based on your example but it appears to work just fine. I did not use Scaffold though, just coded class and I tried the model creating code you had and it hasn't had an issue. I suspect there has to be more to this though because with just the "Assignee" class, EF convention is expecting an "Assignees" table, so I suspect there is more mapping being set up.
Tested with EF Core 2.0.3 and 2.2.4
DB: used the OP's script.
Entity:
[Table("Assignee")]
public class Assignee
{
public int AssigneeId { get; set; }
}
I had to use the Table attribute to map to the table name.
Context:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Assignee>(entity =>
{
entity.Property(e => e.AssigneeId).HasColumnName("AssigneeID");
});
}
as-per OP comment.
Test:
[Test]
public void TestIncrement()
{
using (var context = new TestDbContext())
{
var newItem = new Assignee();
context.Assignees.Add(newItem);
context.SaveChanges();
}
}
Works as expected.
However, what I'd normally have for the entity:
[Table("Assignee")]
public class Assignee
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column("AssigneeID")]
public int AssigneeId { get; set; }
}
And then nothing for this column needed in the context OnModelCreating override.
I suspect that there is some additional configuration lurking somewhere given there is no mention of the table name issue, either manually added or via scaffold that is goofing up EF. I was full-on expecting EF to fail without the Key/DbGenerated attributes, but it seemed to work just fine.
Edit: Also tried this with scafolding running Scaffold-DbContext across the existing schema. Again, worked without an issue.
For comparison against your tests:
Generated DbContext: (Unaltered save removing the warning and connection string details.)
public partial class AssigneeContext : DbContext
{
public AssigneeContext()
{
}
public AssigneeContext(DbContextOptions<AssigneeContext> options)
: base(options)
{
}
public virtual DbSet<Assignee> Assignee { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Data Source=machine\\DEV;Initial Catalog=Spikes;uid=user;pwd=password;MultipleActiveResultSets=True");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
modelBuilder.Entity<Assignee>(entity =>
{
entity.Property(e => e.AssigneeId).HasColumnName("AssigneeID");
});
}
}
Generated Entity: (Unaltered)
public partial class Assignee
{
public int AssigneeId { get; set; }
}
I did figure out why my table annotation was needed. EF Core (Not sure if applies to EF6 as well) was basing the convention for the table name on the DbSet variable name in the DbContext. I couldn't see any config difference with the scaffold generated context and my own, except the DbSet name. I renamed my original DbContext's DbSet name to "Assignee" and it worked without the Table attribute.
That said, based on the information present your code should work. Something is lurking in the details because this example does work so you will need to provide more detail about an example that definitely doesn't work in your case.
I have a Table "IncomingChecks" in my database. I've created it using EF Code first. Now, I've added a view to my database based on this table named "ViewIncomingChecks" using Sql Server Management Studio and I want to use its data in my app using Entity Framework.
I copied the model class and changed its name and added it to the context:
public class ViewIncomingCheck
{
[Key]
public int Id { get; set; }
//...
}
public class CheckDataContext : DbContext
{
public virtual DbSet<ViewIncomingCheck> ViewIncomingChecks { get; set; }
//...
}
now when I run the app, it throws an exception saying the DB Context has been changed and needs a migration. I even tried to add a migration (which seems to be the wrong option) and when I add the migration, it says that the object ViewIncomingChecks is already in the database.
How can I use this view in my code?
Edit
My current solution is to have another context just for the views. This way it doesn't conflict with the EF Migrations. Is this the best option or is there a better way to deal with it.
According to what I have done in my project:
First add public virtual DbSet<ViewIncomingCheck> ViewIncomingChecks
{ get; set; } to your DbConext
Now create a migration something called ViewDbSetAdded
Remove all the code from the both Up and Down method and it will look like as follows:
Migration Code:
public partial class ViewDbSetAdded : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
Now run update-database command and it will run an empty migration.
I was on a Spike branch, playing around with EF Migrations and once I got what I wanted, created the actual dev branch from scratch (based on a previous branch that does not have any DB or ORM related code at all).
The new code
I have a context that inherits from DbContext with this DbSet:
public DbSet<Warehouse> Warehouses { get; set; }
And Warehouse contains this:
public class Warehouse
{
public string Code { get; set; }
public string Name { get; set; }
}
Migrations
If I run
add-migration Warehouse
I get a file called 201708040819010_Warehouse.cs, which contains this:
public override void Up()
{
RenameTable(name: "dbo.Warehouses", newName: "Warehouse");
DropPrimaryKey("dbo.Warehouse");
AddColumn("dbo.Warehouse", "Code", c => c.String(nullable: false, maxLength: 128));
AlterColumn("dbo.Warehouse", "Name", c => c.String(maxLength: 100));
AddPrimaryKey("dbo.Warehouse", "Code");
CreateIndex("dbo.Warehouse", "Name", unique: true);
DropColumn("dbo.Warehouse", "Id");
DropColumn("dbo.Warehouse", "Abbreviation");
DropTable("dbo.People");
}
Which is not at all what I expected.
What's wrong
All those renames, alter column and drop columns seem to suggest that somehow Migrations is convinced that it needs to update an existing table in an existing db.
But that's not true, because I removed my old localdb, am working on a completely new branch and on a new migration.
Not completely out of the blue
I did however have a Warehouse class (when playing around in that Spike branch) that contained an Id, Name and Abbreviation.
But that's old news. And doesn't physically exist anymore.
What I suspect is going on
Is that Visual Studio is tripping over itself and is basing the new Migrations on information that is stored in it's temporary folders. I did a clean of what looked like it could be related based on this post, but to no positive effect.
Update
DbContext
public class MyDbContext : DbContext, IMyDbContext
{
public MyDbContext()
:base("MyDb")
{
Configuration.LazyLoadingEnabled = false;
Database.SetInitializer(new NullDatabaseInitializer<MyDbContext>());
}
public DbSet<Warehouse> Warehouses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations
.AddFromAssembly(Assembly.GetExecutingAssembly());
modelBuilder.Conventions
.AddFromAssembly(Assembly.GetExecutingAssembly());
}
}
EF Migrations config
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MyDbContext context)
{
}
}
Question
What can I do to fix this (weird) behaviour?
I found it. The cause was this:
I didn't notice this before because you only see it when you use -verbose on update-database. Which I don't do unless something's not working (like now).
And the reason behind this is that to run, you need to have a startup project, which in my case is my REST API. As it doesn't have a connectionstring (yet, on purpose), rather than giving an error, Migrations assumes that I want to use my .\SQLEXPRESS instance.
Since I didn't provide a connectionstring on my Spike either, I was working on SQLEXPRESS without noticing, and was now checking against the old table definition, causing these renames and drops instead of a clean create.
... quite the (annoying) assumption. I would have preferred an error.
Update-Database is outputting this error.
Table 'external_service.external_service.products' doesn't exist
Here is some Update-Database -Verbose output.
Target database is: 'external_service' (DataSource: something, Provider: MySql.Data.MySqlClient, Origin: Configuration).
Applying explicit migrations: [201503091803430_1.0.1].
Applying explicit migration: 201503091803430_1.0.1.
alter table `external_service.products` drop column `test`
This is what the db migration looks like...
public partial class _101 : DbMigration
{
public override void Up()
{
DropColumn("external_service.products", "test");
}
public override void Down()
{
AddColumn("external_service.products", "test", c => c.Boolean(nullable: false));
}
}
Here is the POCO
// Both of these generate the same thing. :/
//[Table("external_service.products")]
//[Table("products", Schema = "external_service")]
[Table("products")]
public partial class Product
{
[Column("productid")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long ProductID { get; set; }
[Column("visible")]
public bool Visible { get; set; }
}
Here is the Migration configuration
internal sealed class Configuration : DbMigrationsConfiguration<SoundDevices.DataAccessLayer.Context.ExternalServiceContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations\ExternalService";
}
protected override void Seed(SoundDevices.DataAccessLayer.Context.ExternalServiceContext context)
{
}
}
I'm using EF 6.1.2 with MySql.Data.Entity 6.9.6 & MySql.Data 6.9.6
If I manually remove the "external_service" from the DbMigration, it works, but that seems incorrect. Am I missing something?
The solution depends on what your naming is meant to be. If your database name is external_service and you want the table to be called products, specify:
[Table("products")]
This would create a table with the fully qualified name external_service.products. In SQL server, this would be external_service.dbo.products (or external_service..products, as dbo is the name of the default schema.
If you were actually trying to create a table products in a schema called external_service within your database, also called external_service, then you would use
[Table("products", Schema = "external_Service")]
This would create a fully-qualified table name of external_service.external_service.products.
You've also mentioned that after you changed something and recreated your migration, it tried to rename or move a table. This indicates that when creating your initial migration, you've not removed the older version. To recreate your initial migration, undo the first one then recreate the new one:
Update-Database -TargetMigration:0
Add-Migration 1.0.1 -Force