Is it possible to change table name "__MigrationsHistory" when using codefIrst?
Problem: I am using Oracle Database and I have rules to create new tables. One of them is that there can not be any table names or fields with special characters.
Refer this Link - Is changing the name of the EF __Migration History table dangerous?
This will explain on how to rename the database and what should be done.
This is a bit late but, could help someone who struggle having multiple DBContexts using the same DB scheme.
In order to rename __MigrationHistory table; create a custom class that implements HistoryContext class and override parents OnModelCreating method. Then create a custom configuration class, pass our custom HistoryContext with SetDefaultHistoryContext method.
Please take a look at System.Data.Entity.Migrations.History.HistoryContext
A custom HistoryContext class;
public class YourHistoryContext : HistoryContext
{
public YourHistoryContext(System.Data.Common.DbConnection dbConnection, string defaultSchema)
: base(dbConnection, defaultSchema)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<HistoryRow>().ToTable(tableName: "YourCustomMigrationHistory"/*, schemaName: "dbo__OrYourCustomScheme"*/);
//Rename Id column name.
//modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasColumnName("Migration_ID");
}
}
Create a custom DbConfiguration class;
public class MigrationHistoryConfiguration : DbConfiguration
{
public MigrationHistoryConfiguration()
{
//this.SetHistoryContext("System.Data.SqlClient",
// (connection, defaultSchema) => new HistoryContext(connection, defaultSchema));
this.SetDefaultHistoryContext((connection, defaultSchema) => new YourHistoryContext(connection, defaultSchema));
}
}
Related
I'm trying to change the ID of the Users table from a string (GUID) to an int and really struggling. I have looked at lots of examples but they seem to be for earlier versions of Identity or vs and for numerous reasons they don't work.
I either get a compiler error
'Microsoft.AspNetCore.Identity.IdentityUser', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore 6[TUser,TContext,TKey,TUserClaim,TUserLogin,TUserToken]' violates the constraint of type 'TUser'.
Or when I create the migration I still get a string column for the ID not an int as I was expecting.
I'm using vs2019. Asp.Net.Core 2.2 and Microsoft.AspNetCore.Identity 2.2
Can anyone help me out, please? Thanks!
First extend the IdenityUser class class as follows so that you can add custom properties:
public class ApplicationUser : IdentityUser<int>
{
}
Then extend the IdentityRole class follows if you use Role in application too. You can keep this safely even you don't want to use it:
public class ApplicationRole : IdentityRole<int>
{
}
Now your ApplicationDbContext should be as follows:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
Now in your ConfigureServices method of the Startup class as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
}
Job done! Now run a brand new migration and apply it.
#TanvirArjel solution also worked with .NET Core 3.1 in my project with modifications. I had added Identity through scaffolding.
Instead of editing ConfigureServices(), I edited IdentityHostingStartup.cs instead and mofified Configure() inside IdentityHostingStartup.cs:
builder.ConfigureServices((context, services) =>
{
services.AddDbContext(options => options.UseSqlServer(context.Configuration.GetConnectionString("IdentityDbContextConnection")));
services.AddIdentity()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders()
.AddDefaultUI(); //add default razor pages for identity (login, register, etc)
});
I have two databases that so happen to have the same table name. Entity is giving me an InvalidOperationException stating "The entity types 'PmsUser' and 'AcctUser' cannot share table 'NGUSERS'...
I created these using a code first approach.
My models for both look something like
[Table("NGUSERS")]
public partial class AcctUser
{
...
and
[Table("NGUSERS")]
public partial class PmsUser
{
...
They each have their own respective connection string to differing databases. What do I need to do to get it to allow the same table name (modifying the Database isn't an option)?
Use two ModelBuilder instead of attributes. Then pass the created DbModel to the DbConnection. Or set the database name in the DbContext. See Entity Framework Connections and Models.
This base class helps to register the model builders with the DbContext:
public abstract class ModelBuilderBase {
protected readonly DbModelBuilder ModelBuilder;
protected ModelBuilderBase(DbModelBuilder modelBuilder) {
ModelBuilder = modelBuilder;
}
public abstract void BuildModel();
}
ModelBuilder implementation:
public class ModelBuilder1 : ModelBuilderBase {
public ModelBuilder1 (DbModelBuilder modelBuilder) : base(modelBuilder)
{ }
public override void BuildModel() {
ModelBuilder.Entity<AcctUser>().ToTable("NGUSERS");
}
}
DbContext:
public class DbContext1 : DbContext {
public DbContext1() : base("Database1") /* set DB name */ {
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
var modelBuilders = new List<ModelBuilderBase> {
new ModelBuilder1(modelBuilder)
};
modelBuilders.ToList().ForEach(x => x.BuildModel());
}
}
Create ModelBuilder2 and DbContext2 for the second DB/Table.
I'm working on a EF 6 project (ModelFirst).
I use a complex type named "UserInfo" in all my tables.
But, when I create my database from my model, columns are prefixed by the name of the complex type ( ex: UserInfo_CreationDate)
Is there a way to define in the model the column name without its prefix (CreationData in place of UserInfo_CreationDate)?
You can use Annotations or the FluentApi.
For FluentApi, override the OnModelCreating method in your dbContext class
and, for each property of class UserInfo, add a HasColumnName definition like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<YourEntity>().Property(s => s.UserInfo.CreationDate).HasColumnName("CreationData");
}
For Annotations, in each property of class UserInfo, add an annotation like this:
public class UserInfo
{
.....
[Column("CreationDate")]
public DateTime CreationDate {get; set;}
.....
}
How to do manual table mapping in Entity Framework 5 using the Code First approach?
What I mean by table mapping is to associate a table name from the database to an entity class with a different name.
This is pretty simple.
[Table("Foo")]
public class Bar {
// properties
}
For fluent api:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>().ToTable("MyTargetTable");
}
I am creating an Entity Framework Code-First model to execute ad-hoc queries against a SQL Server database. I am not including any tables/views from the "dbo" schema in my EF model; instead I am only including tables/views from the "model" schema in my database. I do have duplicate names of objects in my database that are separated only by schema (e.g. "dbo.Child" and "model.Child").
Is there one line I can specify in the DbContext that will say in essence "map all entities in this context to the 'model' schema"? I know that I can map each entity to the proper schema (see below), but I'd like to avoid listing out every entity in my database again.
This is what I know I can do:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Child>().ToTable("Child", "model");
modelBuilder.Entity<Referral>().ToTable("Referral", "model");
// 100 lines later...
modelBuilder.Entity<Exit>().ToTable("Exit", "model");
}
This is what I'd like to do:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new MapAllEntitiesToSchemaConvention("model"));
}
I couldn't find anyway to do this out of the box in EF 4.2, but I needed all my entities to be in a different schema so I hacked this up in an attempt to keep things DRYer. It uses the same underlying pluralization engine as EF, and the overrides are there incase entities need to specify the table name.
A reference to System.Data.Entity.Design is needed.
public class BaseConfiguration<TEntityType> : EntityTypeConfiguration<TEntityType> where TEntityType : class
{
private readonly static PluralizationService ps = PluralizationService.CreateService(new CultureInfo("en-US"));
public BaseConfiguration() : this(ps.Pluralize(typeof(TEntityType).Name)) { }
public BaseConfiguration(string tableName) : this(tableName, MyContext.Schema) { }
public BaseConfiguration(string tableName, string schemaName)
{
ToTable(tableName, schemaName);
}
}
I define the schema name via a constant string in MyContext, ie:
public class MyContext : DbContext
{
public const string Schema = "my";
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new SnapshotConfiguration());
}
}
And my entities configurations look like:
public class SnapshotConfiguration : BaseConfiguration<Snapshot>
{
...
}
Caveat: I still need configuration's for each entity I want in the correct schema - but the jist of it could be adopted elsewhere.