EF7 Identity custom table name first seed - entity-framework

I have created a new clean asp.net 5 project (rc1-final), I just need to change default ef identity table name.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(ModelBuilder builder)
{
// On event model creating
base.OnModelCreating(builder);
// Define table name
builder.Entity<IdentityUser>().ToTable("BackEnd_AspNetUsers").Property(p => p.Id).HasColumnName("UserId");
builder.Entity<ApplicationUser>().ToTable("BackEnd_AspNetUsers").Property(p => p.Id).HasColumnName("UserId");
builder.Entity<IdentityUserRole<string>>().ToTable("BackEnd_AspNetUserRoles");
builder.Entity<IdentityUserLogin<string>>().ToTable("BackEnd_AspNetUserLogins");
builder.Entity<IdentityUserClaim<string>>().ToTable("BackEnd_AspNetUserClaims");
builder.Entity<IdentityRole>().ToTable("BackEnd_AspNetRoles");
}
}
I get following error
InvalidOperationException: Cannot use table 'BackEnd_AspNetUsers' in schema '' for entity 'ApplicationUser' since it is being used for another entity.

These lines here show you are trying to setup mappings for both the base identity classes and your application's inherited version of these classes;
builder.Entity<IdentityUser>().ToTable("BackEnd_AspNetUsers").Property(p => p.Id).HasColumnName("UserId");
builder.Entity<ApplicationUser>().ToTable("BackEnd_AspNetUsers").Property(p => p.Id).HasColumnName("UserId");
You don't need both, you should only have the inherited one specified - ApplicationUser.

In your case you should use ForSqlServerToTable("newtablename")
builder.Entity<IdentityUser>().ForSqlServerToTable("BackEnd_AspNetUsers").Property(p => p.Id).HasColumnName("UserId");
builder.Entity<ApplicationUser>().ForSqlServerToTable("BackEnd_AspNetUsers").Property(p => p.Id).HasColumnName("UserId");

Related

Can I add a primary key and a unique constraint in EFCore

I'm manually moving from .NET Framework to .NET Core and working on the EF and DTOs.
I'm not enjoying this - I have read indexes are not supported via annotation and as such, am currently mixing fluent api and annotations which is a code smell. However, it appears as if I must proceed with this combination.
My question is if I can achieve this only with fluent api. My table has both a primary key and a unique constraints.
My object looks like
class Person
{
public int Id {get;set;}
public string UniqueToken {get;set;}
}
However, I am unable to add the following
modelBuilder.Entity<Person>()
.HasKey(a => a.Id)
.HasIndex(a => a.UniqueToken).IsUnique(); //this is what I would like to add but I can't.
I've attempted something which feels like a hacky work around
modelBuilder.Entity<Person>()
.HasKey(a => a.Id);
modelBuilder.Entity<Person>()
.HasIndex(a => a.UniqueToken).IsUnique();
Again, adding this entry twice seems a little bleugh… Fluent appears to want to simply chain the methods.
I have read on this, but I'm getting very lost. Is it possible to add both the primary key and unique constraint ?
Better you separate your entity configurations from OnModelCreating method with IEntityTypeConfiguration interface as follows:
public class PersonConfiguration : IEntityTypeConfiguration<Person>
{
public void Configure(EntityTypeBuilder<Person> builder)
{
builder.HasKey(a => a.Id);
builder.HasIndex(a => a.UniqueToken).IsUnique();
}
}
Now you can add configuration for all of your Db entities like PersonConfiguration and register all of them at once as follows:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(typeof(PersonConfiguration).Assembly);
}
This will give you more separation of concern and readability!

Working with Schemas in EF Code First Migrations

I suppose this question is a cosmetic one; when you initially create an EF migration, it puts the schema in by default; for example:
public override void Up()
{
DropPrimaryKey("dbo.MyTable");
AddPrimaryKey("dbo.MyTable", "NewField");
This seems fine, unit you see the key name that it generates as a result (it has dbo in the key name).
I realise that one way around this is to specify the key name directly. Are there any other options, for example, can the schema be specified for a block, but not included in the specific modifications? For example:
public override void Up()
{
UseSchema("dbo");
DropPrimaryKey("MyTable");
AddPrimaryKey("MyTable", "NewField");
I realise that you can simply omit the schema name; i.e., this will work:
public override void Up()
{
DropPrimaryKey("MyTable");
AddPrimaryKey("MyTable", "NewField");
But how would I then deal with a situation where there were more than a single schema?
You can specify default schema using HasDefaultSchema method on DbModelBuilder class instance.
modelBuilder.HasDefaultSchema("schemaName");
You can also set schema for each entity using ToTable method on EntityTypeConfiguration<TEntityType> class instance. Which will generate migration scripts with provided schema for desired entity/ies.
modelBuilder.Entity<TEntity>().ToTable("tableName", "schemaName")
You can also use Table attribute to set schema for entity.
[Table("tableName","schemaName")]
Or you can write your own custom convention
public class DynamicSchemaConvention : Convention
{
public CustomSchemaConvention()
{
Types().Configure(c => c.ToTable(c.ClrType.Name, c.ClrType.Namespace.Substring(c.ClrType.Namespace.LastIndexOf('.') + 1)));
}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new CustomSchemaConvention());
}
Related links:
DbModelBuilder.HasDefaultSchema Method
EntityTypeConfiguration.ToTable Method
TableAttribute Class
Entity Framework 6 - Code First: table schema from classes' namespace
Entity Framework Custom Code First Conventions (EF6 onwards)

Ignore Entities by Default

I have an existing database, to which I'd like to add Entity Framework mappings for just a handful of tables/entities. Is there a way to ignore all entities by default, and then selectively include them?
I have this in the context constructor to not migrate changes:
Database.SetInitializer(new NullDatabaseInitializer<Context>());
And then I have the following fluent code to map the existing entities:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Cube>()
.Map(e => e.ToTable("tblCubes"))
.HasKey(e => e.CubeId);
...
However, when I run any EF queries, I get the error:
One or more validation errors were detected during model generation.
EntityType 'xyz' has no key defined. Define the key for this EntityType
Rather than using modelBuilder.Ignore<xyz>(); on every existing and future entity, can't I just get EF to ignore all by default, and only map those I choose/include?
EDIT============
One of my EF entities (CubeFact) has relational properties to other classes like this one below to the Year class:
private Year _year;
public Int16 YearId { get; set; }
public Year Year { get { return _year ?? (_year = Year.GetYearById(YearId)); } set { _year = value; } }
The Year class then links to a Fact class, which is one of the classes failing validation. But neither the Year class nor the Fact class have been explicitly mapped. Does EF follow these relationships and then validate, even if I haven't explicitly told it about the relationships?

Can I add a discriminator via a custom code first convention?

I add a discriminator column to all my entities in order to facilitate soft delete.
Currently I do it by specifying it on each entity one by one:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>().Map(m => m.Requires("IsDeleted").HasValue(false));
modelBuilder.Entity<Bar>().Map(m => m.Requires("IsDeleted").HasValue(false));
//etc etc
}
What I'd like to be able to do is specify it as a Custom Code First Convention. My entities all inherit from a ModelBase class. So I can create a custom convention to map to stored procedures like this:
modelBuilder.Types<ModelBase>().Configure(m => m.MapToStoredProcedures());
but this is not available:
modelBuilder.Types<ModelBase>().Configure(m => m.Requires("IsDeleted").HasValue(false));
So, is there any way to add a discriminator to all entities that inherit from ModelBase other than doing it one by one?

EF5 default table name convention causes 'Invalid object name' exception

I have a model with several entities in my MVC4 project with VS 2012. Recently I added a view to my DB named 'vwTeacherNames' and I tried to update the model and I unchecked the Plorizing option for that update.
Then, I rename my entity to 'TeacherName'. Now when I tun the Prj, this exception is thrown where I define a DropDownList for teachers:
Invalid object name 'dbo.TeacherNames'.
I tried many ways such as using custom tool, removing the .tt files and generating the again, ... However the problem stays firm!
So, how can I tell the EF the right table(in fact view) name which is vwTeacherNames?
Thanks a lot
Found it! and I add it here with some more tweaks:
public class myDbContext : DbContext
{
public PtDbContext()
: base("DefaultConnection")
{
}
... //some entities
//Here it is:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<TeacherName>().Property(t => t.FullName)
.HasColumnName("TeacherName");
modelBuilder.Entity<TeacherName>().ToTable("vwTeacherNames", schemaName: "dbo");
}
}
Update: Why waisting your time by defining what you previously defined?! Just kill the default table naming convention and enjoy progressing your Prj:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Adding this line tells the EF not to go through that convention
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
So, It should builds up your queries by EntitySetName and EntityName properties of your entities which the first of is the DB table name and the second is your entity name which you use in your DbContext.