New to IdentityServer 4. I followed the IdentityServer4 EntityFramework sample here on the documentation.
After the migration script is run
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
It works and now my application has 3 DB Contexts.
ApplicationDbContext
PersistedGrantDbContext
ConfigurationDbContext
My question is what are the two DB contexts for? What is the difference between the application db context and the other two?
If I update or add any models, do I need to update all three? Or when should I run a migration on the ApplicationDbContext and when to run on the other two.
Any insight or literature on these is appreciated.
Thanks.
Figured it out. Leaving this for anyone confused about this as I was.
There are 3 DB contexts and, as #Jasen mentioned, it is to split up access to the entities, or tables.
IdeneityServer4 + EntityFramework + ASP.NET Identity creates the following tables in the database:
The contexts are used to reference the following:
ApplicationDbContext - responsible for users involved with ASP.NET Identity so tables
dbo.AspNetRoleClaims
dbo.AspNetRoles
dbo.AspNetUserClaims
dbo.AspNetUserLogins
dbo.AspNetUserRoles
dbo.AspNetUsers
dbo.AspNetUserTokens
PersistedGrantDbContext - responsible for storing consent, authorization codes, refresh tokens, and reference tokens
dbo.PersistedGrants
ConfigurationDbContext - responsible for everything else remaining in the database
So in regards to migrations, if I update any of the AspNet Identity models (i.e. ApplicationUser) then I would run the migration on the ApplicationDbContext. Any client tables or other scopes would be run on the ConfigurationDbContext. And to access the entites (or tables) would be the corresponding context.
Related
.NET6 EFCore & Cosmos Migration issue. Need some help.
Hello folks. I am new in the world of .Net and I am facing an issue that Google has failed to help me solve. You're kind of my last regard.
So. I am trying to connect to an Azure Cosmos DB from my little HomeControlCenter Project using EFCore 6.0.3
The Error:
Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Migrations.IMigrator'. This is often because no database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext>
object in its constructor and passes it to the base constructor for DbContext.
My Program.cs:
builder.Services.AddDbContext<ControlCenterContext>(options =>
options.UseCosmos(builder.Configuration.GetConnectionString("DefaultConnection"), "ToDoList"));
My DbContext Impl:
public class ControlCenterContext : DbContext
{
public ControlCenterContext(DbContextOptions<ControlCenterContext> options) : base(options)
{
}
}
I also tried to use an override of OnConfiguring instead of the Program.cs line.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseCosmos(
"<AccountEndpoint>",
"<accountKey>",
databaseName: "ToDoList");
Nothing helped. When ever I run dotnet ef migrations add "initialSetup" I get the error mentioned above.
I read the error carefully and as you can see, I did apply all the necessary constructor params & other additions... I even tried to create a vanilla project and do the same all over again...
I couldn't find anything official from Microsoft, but the author of this blog states migrations using EF Core for CosmosDb are not supported: https://www.thereformedprogrammer.net/an-in-depth-study-of-cosmos-db-and-ef-core-3-0-database-provider/#1-no-migrations-can-cause-problems
This makes sense since CosmosDB is a document database, so it has no schema, it's just a bunch of JSON files. I ran into this issue when I wanted to use migrations to make seed data. The only solution I could think of was to create a separate project that uploaded the seed data with static values. But again, this was only seed data and not schema updates.
I am looking at samples for IdentityServer 4 for production which doesnt have this annoying InMemory 'this and that'. Basically we need to configure the IdentityServer's IdentityResource, ApiResource, Client, Scope (basically everything) from database.
I have got following (so far) in my code, But not sure how to get all above from the database.
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<RegistrationContext>()
.AddDefaultTokenProviders();
Any help or pointers are much appriciated.
This is for IdentityServer4, dotnet core, and EF Core.
I am working on a ASP.NET MVC 5.1 project, I would using the ASP.NET Identity feature and code first.
By default, the ASP.NET Identity having their own datacontext (IdentityModels.cs) which inherit Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext.
Because i afraid to influence the Identity model.
So i create another context inherrit DbContext , and create another migration configuration by following command:
enable-migrations -ContextTypeName PosApp.Models.OtherContext -MigrationsDirectory:OtherContextMigrations
And using specific configuration command line to update database:
Add-Migration -ConfigurationTypeName
PosApp.OtherContextMigrations.Configuration -Name GenDB Update-Database
-ConfigurationTypeName PosApp.OtherContextMigrations.Configuration
However, i found that it make the migration conflict between tables.
For example:
DataContext A and Configuration A:
Generate Table: Blog , Post , Comment
DataContext B and Configuration B:
Generate Table: User, but reference to Blog (1:N, that mean 1 user can have own multi blogs).
If i type command line - add-migration base on Config B.
The Blog table will be generate again, and conflict because the table exist on Config A.
Even i can override OnModelCreating() event and using modelBuilder.ignore<T> , but it resulting a mess.
So do i avoid multi config of migration?
Or any advantage on it?
You are on the right track using moddelBuilder.ignore. In your identityDbContext add:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<Blog>();
base.OnModelCreating(modelBuilder);
}
Then, to use your relationship from the User to the Blog, create a new data-context inheriting from IdentityDbContext and don't add a migration to it.
The application I develop is deployed to severeal environments (development, test, staging, production).
While developing I created the entity model from the existing development-database. Everything works fine, but as I wanted to put the application onto the test-environment, I realized the following problem:
The structure of the database is identical in all environments, but the database schema changes from environment to environment. For example there's a Customers table in every database. On my local dev machine it has the schema dbo ([dbo].[Customers]), but in the test environment the schema is test ([test].[Customers]), whilst the schema is stag in the staging environment ([stag].[Customers]) and so forth.
So when I deploy the application in the test environment, it gets no data from the database, because the entity framework expects the data to be found in [dbo].[Customers] but there is no such table, there is just a [test].[Customers].
I know, that I can define a schema other than dbo, but this doesn't help me, because I need a different schema depending on the deployment environment.
Any suggestions?
Somehow I think I'll be ending up, asking my DB admin to change the schema to dbo in every database in each environment...
If you are using code first you have to use fluent API approach from linked question and load current schema from configuration file (you will have to modify configuration per each deployment).
If you are using ObjectContext with EDMX you can use Model adapter. Other way which works with DbContext as well is storing EF metadata in files and executing some code which will change schema in ssdl file at application startup.
I cannot get the Entity Framework to work against SQL Azure. Is this just me or is it not intended to be compatible? (I have tried the original release of EF with VS2008 as well as the more recent VS2010 Beta 2 version)
To check this I created the simplest scenario possible. Add a single table to a local SQL Server 2008 instance. The table has two columns, a primary key of type integer and a string column. I add a single row to the table with values of (1, foobar). I then added exactly the same setup to my SQL Azure database.
Created a console application and generated an EF model from the local database. Run the application and all is good, the single row can be returned from a trivial query. Update the connection string to connect to the SQL Azure and now it fails. It connects to the SQL Azure database without problems but the query fails on processing the result.
I tracked the initial problem down using the exception information. The conceptual model had the attribute Schema="dbo" set for the entity set of my single defined entity. I removed this attribute and now it fails with another error...
"Invalid object name 'testModelStoreContainer.Test'."
Where 'Test' is of course the name of the entity I have defined and so it looks like it's trying to create the entity from the returned result. But for some unknown reason cannot work out this trivial scenario.
So either I am making a really fundamental error or SQL Azure is not compatible with the EF? And that seems just crazy to me. I want to use the EF in my WebRole and then RIA Services to the Silverlight client end.
While I haven't done this myself I'm pretty sure that members on the EF team have, as has Kevin Hoffman.
So it is probably just that you went astray with one step in your porting process.
It sounds like you tried to update the EDMX (XML) by hand, from one that works against a local database.
If you do this most of the changes will be required in the StorageModel element in the EDMX (aka SSDL). But it sounds like you've been making changes in the ConceptualModel (aka CSDL) element.
My guess is you simply need to replace all references to the dbo schema in the SSDL with whatever schema is the SQL Azure schema.
Hope this helps
Alex
To answer the main question - Yes, at least the Entity Framework v4 can be used with SQL Azure - I haven't honestly tried with the initial version (from the .Net Framework 3.5. SP 1).
A little while back I did a complete project and blogged about the experience: http://www.sanderstechnology.com/?p=9961 Hopefully this might help a little bit!
Microsoft's Windows Azure documentation contains How to: Connect to Windows Azure SQL Database Using the ADO.NET Entity Framework.
After creating your model, these instructions describe how to use SQL Azure with the Entity Framework:
Migrate the School database to SQL Database by following the instructions in How to: Migrate a Database by Using the Generate Scripts Wizard (Windows Azure SQL Database).
In the SchoolEFApplication project, open the App.Config file. Change the connection string so that it connects to your SQL Database.
<connectionStrings>
<add name="SchoolEntities"
connectionString="metadata=res://*/SchoolDataModel.csdl|res://*/SchoolDataModel.ssdl|res://*/SchoolDataModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=<provideServerName>.database.windows.net;Initial Catalog=School;Integrated Security=False;User ID=<provideUserID>;Password=<providePassword>;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=False""
providerName="System.Data.EntityClient"/>
</connectionStrings>
Press F5 to run the application against your SQL Database.