Migration to postgres doesn't work correctly - c#

So I've built a very Asp.Net Core 3.0 MVC app, with some models and when I run the add-migration initial, it runs with no errors and it shows up in the solution explorer, but no changes occur in the actual PostgreSQL database.
I've noticed when I mess with the connection string, and put wrong stuff there, it only matters when I want to remove the migration, it gives no error when I want to add the migration.
I'm using .net core 3.0 , PostgreSQL 12.1.
ConfigureServices in Startup.cs:
services.AddEntityFrameworkNpgsql().AddDbContext<MyDbContext>(opt => opt.UseNpgsql(Configuration.GetConnectionString("DbConnection")));
Connection string in appsettings.json:
{
"ConnectionStrings": {
"DbConnection" : "User ID =postgres;Password=pass;Server=localhost;Port=5432;Database=MyDb;Integrated Security = True; Pooling=true"
},
DbContext:
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
public DbSet<PirkVald> PirkValds { get; set; }
}
Console output when running add-migration initial
Build started...
Build succeeded.
Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 3.1.0 initialized 'MyDbContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL' with options: None
To undo this action, use Remove-Migration.

You need to use Update-database to apply your migration and refresh your PostgreSQL database

Related

Entity Framework Core database migration in C#

I'm trying to migrate a database (the database was already created beforehand) through the startup of an ASP.NET Core 3.1 web app. I created the migration by enabling migrations in the Visual Studio Package Manager Console:
enable-migrations
And then created a migration:
Add-Migration TestTable –Context MyDbContext
TestTable creates a simple table that I use to test the migration.
I want to be able to migrate the database on startup, without the need to use the Visual Studio Package Manager Console, without the need to use the update-database command.
I have tried this:
var migrationAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyConnectionString"),
sql => sql.MigrationAssembly(migrationAssembly))));
I get no errors, but the table never gets created. I tried simple crud operations on the table but they throw error because the table doesn't exist, also I checked in the SQL Server Object Explorer and the table isn't there.
Any thoughts will be greatly appreciated.
Best
Take a look at this code
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext dataContext)
{
// migrate any database changes on startup (includes initial db creation)
dataContext.Database.Migrate();
...
}
here's the reference link:
https://jasonwatmore.com/post/2019/12/27/aspnet-core-automatic-ef-core-migrations-to-sql-database-on-startup

.NET Framework and Entity Framework Core: How can I get hold of the connection string

I've installed EF Core in a .NET Framework 4.7.2 class library. This is just a project containing some specific functionality, not the StartUp project in the solution. The project with EF Core is then referenced by the main project, where the web.config and IoC setup lives. The solution is for a web site.
According to this page, .NET Framework 4.7.2 is supported.
The problem is injecting or otherwise fetching the connection string, or probably any other configuration/appsettings value.
Let's say this is my DbContext class:
public class PersonContext : DbContext
{
public DbSet<Person> Persons { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
if (ConfigurationManager.AppSettings["ConnectionString"] == null)
{
throw new Exception("Hey!");
}
optionsBuilder.UseSqlServer(ConnectionString);
}
}
}
When I run commands like Add-Migration or Remove-Migration, the AppSettings["ConnectionString"] is null, and the exception gets thrown.
I think this is due to the application being in "design mode", and the web.config hasn't been read. I need to be able to specify different connection strings for different environments.
Any ideas to how I can get the connection string from either the <appSettings> or the <connectionStrings>?
Edit: I also want to add that the solution uses Structuremap for IoC, and I can't inject into the DbContext when running the migration commands in the package manager console.
Try this:
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionStringName"].ConnectionString;

Code First Entity Framework with ASP.NET Core: Initial migration seems to expect tables already exist

I'm trying to create a Code First Entity Framework ASP.NET Core 2 project in Visual Studio Code. I've been following the Create a Web API with ASP.NET Core MVC and Visual Studio Code on Linux, macOS, and Windows tutorial, which uses an in-memory datastore as its DbContext. I'm trying to move this to LocalDB.
The tutorial Getting Started with EF Core on ASP.NET Core with a New database suggests I should be able to do this with a migration.
Once you have a model, you can use migrations to create a database.
Open the PMC:
Tools –> NuGet Package Manager –> Package Manager Console
Run Add-Migration InitialCreate to scaffold a migration to create the initial set of tables for your model. If you receive an error stating The term 'add-migration' is not recognized as the name of a cmdlet, close and reopen Visual Studio.
Run Update-Database to apply the new migration to the database. This command creates the database before applying migrations.
The VS Code equivalent of using the Package Manager Console seems to be:
dotnet ef migrations add InitialCreate
I've added EF's Design namespace with...
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet restore
And have the reference in my csproj:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.1" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>
But when I try that the dotnet ef migrations add command afterwards, it acts like the table for my TodoItems model needed to already exist in the database. It was my understanding that the migration would create the tables based on my models.
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'.
What needs to be done to ensure tables are created based on my models?
The only gotcha I can think of offhand is that I have the connection string inline rather than in appsettings.json, but I'm not sure why that'd be a big deal, unless the migration is looking for a config by default.
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, those are the only changes I've made to the TodoApi tutorial's code to move from the in-memory db to LocalDB.
Update: Fwiw, I tried changing the database name in the connection string..
string strCxn = "Server=(localdb)\\mssqllocaldb;Database=Contacts2;Trusted_Connection=True;MultipleActiveResultSets=true";
(Changing Contacts to Contacts2, just in case it thought that, since it found the Contacts db initially, a migration had already taken place...)
That didn't work either, though the error changed in a way that suggests the connection string is working and being read.
Cannot open database "Contacts2" requested by the login. The login failed.
Login failed for user 'COMPUTER-NAME\UserName'.
As part of the DbContext's constructor, I was seeding data...
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;}
}
Part of the migration's execution involves instantiating the DbContext obviously before the tables for the DbSets are migrated over. Since the constructor, in this example, requires accessing States, and because the migration hasn't gotten to the point it's created the States table to pull from yet, the migration blows up.
As Kirk mentions, if I take out the seeding, I'm fine. And if you want to seed, you need to move that somewhere other than the constructor, even though the seeding in the constructor works fine outside of a migration attempt/in normal Kestrel testing.
For me, I just commented out this.MinimallySeedDatabase(); when I ran the migration.

how to properly promote Entity Framework code-first migrations into production?

In my ASP.NET EF 6 app, I have the following Configuration:
internal sealed class Configuration : DbMigrationsConfiguration<Gcim.Management.Module.BusinessObjects.ManagementDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(Gcim.Management.Module.BusinessObjects.ManagementDbContext context)
{
}
}
In my project, I have EF code-first migrations enabled.
I'm able to run add-migration, as well as update-database from the VS Package Manager prompt.
However, when my entities change, adding a migration, and updating database only works in dev environment.
When I publish my ASP.NET project, install it on production IIS, and run, I still get this error:
The model backing the 'ManagementDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
What else do I need to do in order to force the incremental DB changes in production, without data loss?
You can execute a given migration file against a given environment (in this case, your production environment) by using the migrate.exe application included as part of the Entity Framework nuget package. You'll need to execute your latest migration against your production environment before publishing your web application - once this has been done, the newly deployed application will work correctly.
You do this by specifying the connection string and .dll containing the migration class(es), as well as possibly a specific migration. For example:
Migrate.exe Gcim.Management.Module.BusinessObjects.dll /connectionString="Data Source=[YourProductionDatabase];Initial Catalog=[YourTable];Integrated Security=SSPI" /connectionProviderName="System.Data.SqlClient" /targetMigration="[NameofYourMigration]"
Documentation on migrate.exe can be found here: https://msdn.microsoft.com/en-us/data/jj618307.aspx

SQLite in ASP.NET Core with EntityFrameworkCore

How do you add and use an SQLite database in an ASP.NET Core web application, using EntityFramework 7 ?
I dived into ASP.NET Core the moment I heard about it and created my first web application, I suddenly had a bunch of data that I wanted to store and SQLite seemed like the obvious choice.
Since I wanted it to stay with my application, keep it lightweight, simple and avoid setting up a separate database.
So how would one go about creating an SQLite database in ASP.NET Core?
ASP.NET Core - now formerly known as ASP.NET MVC 6
EntityFramework Core - now formerly known as EntityFramework 7
Update: November 4th, 2016.
Reformatting - pictures to code examples.
Info:
Keep in mind that in some code examples, code that was generated by the visual studio template have been omitted.
Update: July 11th, 2016.
.NET Core and EntityFrameWork Core version 1.0 is upon us!
So this guide deserves a little update
Step 1:
Create your application.
Step 2:
Get the necessary packages
Microsoft.EntityFrameworkCore 1.0.0
Microsoft.EntityFrameworkCore.SQlite 1.0.0
Step 3:
Create your context:
(The Context will be a class that you create)
public class DatabaseContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Filename=MyDatabase.db");
}
}
Step 4:
Add your context to your services:
(Located in your Startup class)
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlite().AddDbContext<DatabaseContext>();
}
Step 5:
Create your database on startup, by adding it to the startup method
(Located in the Startup class)
public Startup(IHostingEnvironment env)
{
using(var client = new DatabaseContext())
{
client.Database.EnsureCreated();
}
}
Et Voíla!
Now you will be able to use SQLite in your ASP.NET Core applications.
The old guide still applies regarding how you create your models as well as using your database context.
Update: May 28th, 2016.
.NET Core RC2 and EntityFramework Core RC1 have been released.
They have improved and simplified the steps for setting up SQLite.
But I'm experiencing some trouble with it and can't replicate it, because of an error with the Newtonsoft.Json library and NuGet.
I recommend sticking to the RC1 libraries if you want to do this, for now!
Step 1:
Create your ASP.NET web application
Step 2:
Go to Tools -> Nuget Packet Manager -> Manage Nuget Packages for Solution.
Search for EntityFramework.SQLite and check the Include prelease box.
Install the package
Step 3: Creating a context
Create a context class for your database.
Call it whatever you want, but let's go with something that's customiary, like MyDbContext.
Make your new class inherit the DbContext class and override the OnConfiguring method and define your connection like so:
public class MyDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = "MyDb.db" };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
optionsBuilder.UseSqlite(connection);
}
}
Step 4:
Go to the Startup.cs and make sure your database is created at the start of your web application:
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
using (var db = new MyDbContext())
{
db.Database.EnsureCreated();
db.Database.Migrate();
}
}
Secondly we need to add the service:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddEntityFramework()
.AddSqlite()
.AddDbContext<MyDbContext>();
}
Step 5: Defining your Models
Create your models and go to MyDbContext.cs and add a new property for each of your new models (given that you want a table for each!)
Here's an example:
My Model:
public class Category
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string UrlSlug { get; set; }
}
Adding it to my context:
public class MyDbContext : DbContext
{
public DbSet<Category> Categories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = "MyDb.db" };
var connectionString = connectionStringBuilder.ToString();
var connection = new SqliteConnection(connectionString);
optionsBuilder.UseSqlite(connection);
}
}
Step 6: Using the the context
Go to your HomeController and add a new field to your controller.
private readonly MyDbContext _myDbContext = new MyDbContext();
And use it in an ActionResult by passing it to the returned view:
(Now lets assume we have a category in our database)
public IActionResult Index()
{
var category = _myDbContext.Categories.First();
return View(category);
}
So by going to your Index view, you can use our imaginary data from the database. By defining a model in the top of your view like so:
#model MyNameSpace.Models.Category
#{
ViewData["Title"] = "Hey Ho! SO!";
}
<div class="page-header">
<h1>#ViewData["Title"]</h1>
</div>
<div class="container">
#Model.Title
</div>
Now by starting our web application and going to the assigned address we should see a default html page with a fancy bootstrap header, showing this on the page:
The second line is (or would be) the title of our first category in our database.
Entity Framework 7 Docs
This is my first Q&A - if you have any input or something that needs clarifying don't hesitate to comment.
This is a very basic example of how to implement an SQLite database into an ASP.NET Core MVC web application.
Do note that there is several ways to set the connection string for the database, how to use the context and that EntityFramework 7 is still a prerelease
If you want to create an ASP.NET Core web application using SQLite for the database, I highly recommend using Yeoman to scaffold the app for you. You need to first install .NET Core 1.1 SDK (Visual Studio 2015 seems to only include SDK versions 1.0.0 and 1.0.1 at the moment). You then need to install Node.js which comes with npm and then install the following npm packages: yo and generator-aspnet. Then all you have to do is run yo aspnet and answer a few questions.
C:\Development>yo aspnet
? ==========================================================================
We're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes
_-----_ ╭──────────────────────────╮
| | │ Welcome to the │
|--(o)--| │ marvellous ASP.NET Core │
`---------´ │ generator! │
( _´U`_ ) ╰──────────────────────────╯
/___A___\ /
| ~ |
__'.___.'__
´ ` |° ´ Y `
? What type of application do you want to create? Web Application
? Which UI framework would you like to use? Bootstrap (3.3.6)
? What's the name of your ASP.NET application? WebApplication
Afterwards, you will get the following response:
Your project is now created, you can use the following commands to get going
cd "WebApplication"
dotnet restore
dotnet build (optional, build will also happen when it's run)
dotnet ef database update (to create the SQLite database for the project)
dotnet run
Run dotnet restore, dotnet ef database update, and then dotnet run and go to localhost:5000 to make sure the project is running.
Now you can open the project in Visual Studio 2015 (assuming you're on Windows) or Visual Studio Code.
The great thing about this is that Startup.cs, project.json, and appsettings.json files are setup to use SQLite. Also, a SQLite database is created for you:
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
}
project.json:
{
"Microsoft.EntityFrameworkCore.Sqlite": "1.1.0",
"Microsoft.EntityFrameworkCore.Sqlite.Design": {
"version": "1.1.0",
"type": "build"
}
}
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=WebApplication.db"
}
}
Your SQLite database will be located in bin/Debug/netcoreapp1.0. In my case, it is located in C:\Development\WebApplication\bin\Debug\netcoreapp1.0\WebApplication.db
If you want to rename the SQLite database, modify appsettings.json file and run dotnet ef database update.
To learn more about using SQLite database with .NET Core and EF Core, check out this article: .NET Core - New Database
Install Below mentioned packages
PM> Install-Package Microsoft.EntityFrameworkCore
PM> Install-Package Microsoft.EntityFrameworkCore.Sqlite
PM> Install-Package Microsoft.EntityFrameworkCore.Tools
Create Models
Create DBContext class add SQLite connection configuration
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=DBFileName.db");
Run migration commands to start using it
PM> add-migration <MigrationName> //Ex: add-migration IntialMigration
PM> update-database
https://fullstack-lab.co.in/Sqlite-entity-framework-core-quick-start
This article provides simple steps to use SQLite with Asp.net core 3.1
In dotnet 6 :
Your DbContext constructor should look like this: (remove OnConfiguring method from your DbContext.
public PaymentDbContext(DbContextOptions<PaymentDbContext> options) : base(options)
{
}
and in program.cs file, add your service like this:
builder.Services.AddDbContext<PaymentDbContext>(options =>
options.UseSqlite($"Data Source={dbPath}"));
dbPath is your database address.
if you want to update your database and your dbContext file located in a different solutions don't forget to use --startup-project in dotnet ef database update command :) ex:
dotnet ef database update --startup-project ../PaymentProject.Api/PaymentProject.Api.csproj

Categories