I have an MVC5 project with Individual user account authentication. I have make a test registered myself and everythings works. Then for test sake I've added a property to ApplicationUser class, now ti looks like this:
public class ApplicationUser : IdentityUser
{
public string NewPropery { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
Then I've opened the Package Manager Console in Visual Studio 2013 and run:
PM> Enable-Migrations
PM> Add-Migration "NewProperty"
PM> Update-Database
first two commands goes well but fail on the third command and this is the error:
System.Data.SqlClient.SqlException (0x80131904): A network-related or
instance-specific error occurred while establishing a connection to
SQL Server. The server was not found or was not accessible. Verify
that the instance name is correct and that SQL Server is configured to
allow remote connections. (provider: SQL Network Interfaces, error: 26
- Error Locating Server/Instance Specified)
The database is the usual LocalDb created by MVC template, I leave the connection string in the project as it was created:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-NyProject.Web-20160325120840.mdf;Initial Catalog=aspnet-MyProject.Web-20160325120840;Integrated Security=True"
providerName="System.Data.SqlClient" />
Where is the error?
UPDATE 1 - After Steve comment
I use to select the project in Package Manager Console, making the project a "Startup project" this will produce a different error There is already an object named 'AspNetRoles' in the database..
This is true. Should I remove pre-existent tables, and what about my data?
You are getting that error because you have not established a baseline initial migration so EF thinks all your objects need to be created. This is because it builds models based on the code and compares it to the snapshot stored in the last migration, so try this:
1) Comment out the new field.
2) Delete the existing migration.
3) Add a baseline migration: add-migration Initial -IgnoreChanges
4) update-database (now EF has a snapshot to compare changes to).
5) add-migration NewProperty
6) update-database
EF Under the Hood
Related
I have setup two configuration for migration one is for SQL server and another is for MySql. SQL Server migration is now not being used. Now my problem is when I execute Sql Server migration with Update-Database -ConfigurationTypeName InTouchEnterprise.Data.Repository.MySqlMigrations.Configuration -verbose. It gives me following error
Authentication to host 'localhost' for user 'test' using method 'mysql_native_password' failed with message: Access denied for user 'test'#'localhost' (using password: NO)
But If I run the project it gets successfully connected to the database and do all the operation with database correctly. Now I am clue less what could have been wrong.
According to the error message it says that I am not specifying the password but I have specified password in the web.config. below is my connection string.
<add name="IdentityDB" providerName="MySql.Data.MySqlClient"
connectionString="server=localhost;port=3306;database=rtd;uid=test;password=*******" />
Below is code for Configuration class:
internal sealed class Configuration : DbMigrationsConfiguration<InTouchEnterprise.Data.Repository.InTouchEnterpriseDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"MySqlMigrations";
//for mysql
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}
protected override void Seed(InTouchEnterprise.Data.Repository.InTouchEnterpriseDbContext context)
{
}
}
I don't know the exact issue but when I added persist security info in connection string in web.config to true it started working again. Here is my updated connection string.
<add name="IdentityDB" providerName="MySql.Data.MySqlClient"
connectionString="server=localhost;port=3306;database=rtd;uid=root;password=*****;persistsecurityinfo=True" />
I created a new ASP.NET MVC project, I am using code-first. I have added ASP.NET Identity to this project enabled-migrations and can see the tables in my database on sql server express.
I have a "DefaultConnection" which points to my database on sqlserver like so:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=worksmartDB;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
Now, I am confused how to add my entities to the same database via code first? Below is my structure:
Models
Applicant
Template
MyProjectContext(which dervies from DBContext)
public class MyProjectContext: DbContext
{
public MyProjectContext() : base("DefaultConnection")
{
}
public DbSet<Applicant> Applicants { get; set; }
public DbSet<Template> Templates { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
I try to enable migrations for this context but I receive the following error:
The context type 'MyProjectContext' was not found in the assembly 'MyProject'
I want to use same database for identity and entities.
Well I got it to work, not sure if this is the correct method.
However,
When you add identity into a new project, you should do the following:
- Change public ApplicationDbContext()
: base("YourConnection", throwIfV1Schema: false)
Note: this connection string should point to the same database you are going to use
- Run the application in browser
- Register a user (this will create the database for you, if one does not exist)
- Now Enable-Migrations
- Update-Database
And this is one way of adding identity into your project.
I'm having a problem that when I try to access a field in my PartsDbContext I get the following error:
System.Data.SqlClient.SqlException: 'Invalid object name 'fieldName''
It seems that this is because I'm trying to make my PartsDbContext use the same database as my ApplicationDbContext which is used with Identity. I need to know how to setup a 2nd dbcontext to work with EF core that uses/creates a different database.
I've tried creating a 2nd connection string but that gets me this error:
System.Data.SqlClient.SqlException: 'Cannot open database "PartsDb" requested by the login. The login failed.
Login failed for user 'DESKTOP-4VPU567\higle'.'
Here's my code:
appsettings.json
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-PrecisionCustomPC-b14db89e-86ad-4855-a17f-ac64a04339aa;Trusted_Connection=True;MultipleActiveResultSets=true",
"PartsConnection": "Server=(localdb)\\mssqllocaldb;Database=PartsDb"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
PartsDbContext.cs
public class PartsDbContext : DbContext
{
public DbSet<PartsViewModels.Tower> Towers { get; set; }
public DbSet<PartsViewModels.Motherboard> Motherboards { get; set; }
public PartsDbContext(DbContextOptions<PartsDbContext> options)
: base(options)
{
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddEntityFramework()
.AddDbContext<PartsDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("PartsConnection")));
services.AddMvc();
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
});
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
AdminController.cs
[Authorize(Policy = "RequireAdminRole")]
public class AdminController : Controller
{
private readonly PartsDbContext _context;
public AdminController(PartsDbContext context)
{
_context = context;
}
public IActionResult Index()
{
return View();
}
public IActionResult Towers()
{
var model = _context.Towers.ToList();
return View(model);
}
}
The line var model = _context.Towers.ToList(); is where the error is showing up.
Once again. I want to setup my PartsDbContext to work with Entity Framework Core in a way that EF-Core will automatically create the database.
I figured it out. This mostly came about because I accidentally deleted the database that Identity was using and I needed to figure out how to get it back.
Apparently there's nothing wrong with my connection string the way it is. I just needed to go into the package manager and type these commands in this order:
Add-Migration init -Context PartsDbContext
Update-Database -Context PartsDbContext
I found this out because that is what I had to do to get my ApplicationDbContext working again and it turns out that this step is done for you when you create a new MVC Core Web Application in Visual Studio using Individual User Authentication.
So basically the steps for adding more DbContexts is to:
Create a DbContext Class
Create a Connection string for that DbContext in appsettings.json
Add the DbContext to your configured services in Startup.cs
Setup the DbContext in the controllers that will use it.
Open the package manager and run the 2 lines above. (if "-Context" doesn't work try "--context"
Run your program and let EntityFrameworkCore take care of the rest.
First of all, thanks #Joe Higley answer this questions,I want to add more situation to help more people.
My situation is i'm trying to use EF-Identity and Area to create a admin panel, in my admin area own their own controller/models/views..., also contain a new DBcontext.
There is problems, if you try to context.Database.EnsureCreated(); to initialize DB there will show
System.Data.SqlClient.SqlException: 'Invalid object name 'fieldName''
Ref this link Migrations with Multiple Providers
We can use migrations and use --context to set which DbContext you want to run
In VScode you can run
dotnet ef migrations add InitialCreate --context BlogContext
dotnet ef database update
In Package Management Console you can run
Add-Migration InitialCreate -Context BlogContext
Update-Database
In addition to the prior comments, you can use this way:
dotnet ef migrations add InitialCreate --context MyContext
dotnet ef database update --context MyContext
or
Add-Migration InitialCreate -Context MyContext
Update-Database -Context MyContext
I cannot comment yet, but I would like to add to the answer.
Currently I am working my way through this tutorial: https://learn.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/model?view=aspnetcore-5.0&tabs=visual-studio
But I too started out with ApplicationDbContext for Identity. So, I ran into a similar problem. Your answer helped me out, thanks!
The tutorial however suggests a cleaner way to do this.
Add a data model
Scaffold the data model!
This step is huge. It creates the Context class, a connection string in appsettings.json, adds the Context in Startup.cs and more.
For usage of scaffolding take a look at linked tutorial.
Run given commands in the PMC and you are set.
Add-Migration init -Context ModelContext
Update-Database -Context ModelContext
So, I would suggest to use scaffolding as it does the most work for you.
I have set up a Code First using the following DbContext
public class MyDatabaseDbContext : DbContext
{
public MyDatabaseDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
public MyDatabaseDbContext()
: base("MyDatabase")
{
}
public DbSet<MyTable> MyTables { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
I have also set up the connection string to look at the (Local) database
<connectionStrings>
<add name="MyDatabase"
connectionString="Server=(local);Database=MyDatabase;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient"
/>
</connectionStrings>
Also set up the initializer in Global.asax
Database.SetInitializer<MyDatabaseDbContext>(new DropCreateDatabaseAlways<MyDatabaseDbContext>());
I then run the application and call the DbContext (in my case from the controller)
var dbContext = new MyDatabaseDbContext();
var myTableResults = dbContext.MyTables.ToList();
I get the follow error message
An exception of type 'System.Data.SqlClient.SqlException' occurred in EntityFramework.dll but was not handled in user code
Additional information: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 50 - Local Database Runtime error occurred. Cannot get a local application data path. Most probably a user profile is not loaded. If LocalDB is executed under IIS, make sure that profile loading is enabled for the current user.
On Debugging and looking at the dbContext variable > Database > Connection > ConnectionString Property I see the following:
"Data Source=(localdb)\v12.0;AttachDbFilename=|DataDirectory|MyDatabase.mdf;Initial Catalog=MyDatabase;Integrated Security=True;MultipleActiveResultSets=True"
Questions
Why is it pointing to the (localDb)\v12.0 database and not my connection string?
Even so, Why is it not creating the database there anyway as this is on my dev machine?
Is there some kind of convention which I have forgotten about which I need to set.
Your connection string needs to be named MyDatabaseDb
OR
your context class needs to be named MyDatabaseContext.
Entity Framework's convention is for the context class to look for a connection string with the same name + Context. The Db in your class name is extraneous.
I have created a database for use with a NuGet Gallery implementation. I can see the database in sql manager 2012 and I can access it from a test program I wrote, using my connection string. However, when I try to run the Update-Database command in the package manager console, to have EF set up the database, I keep getting the error: "The server was not found or was not accessible.".
Here's more detail:
PM> Update-Database -Verbose
Using StartUp project 'NuGetGallery.Operations'.
Using NuGet project 'NuGetGallery'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
System.Data.ProviderIncompatibleException:
An error occurred while getting provider information from the database.
This can be caused by Entity Framework using an incorrect connection string.
Check the inner exceptions for details and ensure that the connection string is correct. --->
System.Data.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string. --->
System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26
- Error Locating Server/Instance Specified) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
Here's my connection string in the NuGet Gallery MVC site:
<add name="Gallery.SqlServer" connectionString="Server=(localdb)\v11.0;Database=NuGetGallery11;User ID=testuser;Password=notmyrealpassword;Connect Timeout=60" providerName="System.Data.SqlClient"/>
And here's my test program. The connection strings are identical in both applications.
var sqlConnection2 = new SqlConnection(ConfigurationManager.ConnectionStrings["Gallery.SqlServer"].ConnectionString);
sqlConnection2.Open();
using (sqlConnection2) {
var sqlCmd = new SqlCommand("select * from Foo", sqlConnection2);
var foo = sqlCmd.ExecuteReader();
while (foo.Read()) {
int id = foo.GetInt32(0);
var name = foo.GetString(1);
var email = foo.GetString(2);
Console.WriteLine("ID:{0}, Name:{1}, Email:{2}", id, name, email);
}
}
Console.Read();
Any help would be greatly appreciated. Thanks!
My problem was solved in this other post here. You have to set the default project in the manager console AND set the startup project for the solution in order for the update command to find the connection string and also what Aydin said, but in this case that part was already set up for me.
Your problem is that EntityFramework doesn't know that your connection string is named Gallery.SqlServer...
Here's how you can setup entity framework from scratch...
Open VS with Administrative rights (just being cautious)
Create a new Console application
Open the package manager console
Type in: `PM> Install-Package EntityFramework
Open the App.Config file
Add the following
<connectionStrings>
<add name="Gallery.SqlServer" connectionString="Server=(localdb)\v11.0;Database=GalleryExample;" providerName="System.Data.SqlClient"/>
</connectionStrings>
Create a new class called Foo
public class Foo
{
public Foo()
{
this.Id = Guid.NewGuid()
.ToString();
}
public string Id { get; set; }
}
Create a new class called EfContext
public class EfContext : DbContext
{
public EfContext()
: base("Gallery.SqlServer")
{
}
public DbSet<Foo> Foos { get; set; }
}
Open up the package manager console again
PM> Enable-Migrations
PM> Add-Migration InitialMigration
PM> Update-Database
Enjoy your new db....