Entity Framework 6, cannot use Ignore method on the property - c#

Currently, I'm using ASP Identity with MVC 5.I want to remove phone number field from the AspNetUsers table, but when I use add-migration command it causes the following error.
You cannot use Ignore method on the property 'PhoneNumber' on type
'Models.DbModel.User' because this type inherits from the type
'Microsoft.AspNet.Identity.EntityFramework.IdentityUser`
I have already read tons of questions on here, but all of them said you have to ignore property in your base class, however, I don't have any access to the base in this case.
How can I solve this problem?
Update: when I used fluent API inside the OnModelCreating method it worked, I don't want to use it this way so I separated the config class for each entity.
Below is my code:
Derived Entity Class
public class User: IdentityUser
{
public ICollection<Comment> Comments { get; set; }
}
Config class
public sealed class UserConfig : EntityTypeConfiguration<User>
{
public UserConfig()
{
ToTable("dbo", "Users");
Ignore(x => x.PhoneNumber);
Ignore(x => x.PhoneNumberConfirmed);
}
}
Context Class
public class WebsiteContext : IdentityDbContext
{
public WebsiteContext()
: base("XYZ")
{
}
public DbSet<Comment> Comment { get; set; }
//public DbSet<User> User { get; set; }
public static WebsiteContext Create()
{
return new WebsiteContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new CommentConfig());
modelBuilder.Configurations.Add(new UserConfig());
}
}

Try the [NotMapped] attribute from
System.ComponentModel.DataAnnotations.Schema
This might get you around that limitation , it has been used to ignore Enums in the mapping, this might not be exactly what you want

Related

cannot perform override in class inheritance in ADO .NET Entity Model edmx

I have to build a .net web application accessing tables of an existing db.
The db uses different tables for different companies: customers in company "ACorp" are stored in table "ACorpCustomers", those in company "B" are stored in table "BCorpCustomers".
Using ADO .NET Entity Model, I created a different Db Context for each Company:
public partial class ACorpContext : DbContext
{
public ACorpContext()
: base("name=ACorpContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<ACorpCustomer> ACorpCustomers { get; set; }
}
}
The edmx generates also the class
public partial class ACorpCustomer
{
public string Name { get; set; }
public string Phone { get; set; }
}
I created a parent class Customer to be used in the application, with the same properties:
public class ACorpCustomer
{
public virtual string Name { get; set; }
public virtual string Phone { get; set; }
}
I havent't found a way to let the specific entity ACorpCustomers inherit from the parent Customer; the edmx returns the inheritance error, but there is no way to override the properties.
Update
In order to avoid edmx file usage, this is what I finally tried out:
I disabled the __MigrationHistory sql table creation using the AutomaticMigrationsEnabled parameter:
internal sealed class Configuration : DbMigrationsConfiguration<MyDomain.Models.ACorpContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
I disabled the db initialization in the App.config file setting
disableDatabaseInitialization="true"
Then I added a an ADO .NET Entity Model but chose the "code first from database".
In order to be sure not to change the db from the model, I disabled the DB Initializer:
public ACorpContext()
: base("name=ACorpContext")
{
Database.SetInitializer<ACorpContext>(null);
}
Now I expect to be my responsability to be keep in sync the domain model with the db.
Anyway, I feel sure that in case of misalignment no attempt will be done to modify the db.
Without the edmx, I have no more limitations defining inheritance from an abstract class Customer.
I cannot understand why Visual Studio considers this as "Code First" approach, anyway.
Your definition
public partial class ACorpCustomer
has nothing to do with inheritance. partial is a .NET moderator that signifies that your class definition is a part of the bigger definition. For example if you have your class split between 2 code files. .Net "puts" them together and you endup with one type
Here what you seem need to do is
public abstract class Customer
{
public string Name { get; set; }
public string Phone { get; set; }
}
public class ACorpCustomer : Customer
{
// may be, some unique properties here
}
public class BCorpCustomer : Customer
{
// may be, some unique properties here
}
The properties Name and Phone don't even need to be virtual. Looking back into your title, there is nothing that you need to override. Nothing that I see..
This is trivial in Code-First, which you can (and should) use with an existing database. Just map the single Customer entity to the correct table for each DbContext:
public partial class ACorpContext : MyBaseDbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>().ToTable("ACorpContext");
}
public virtual DbSet<Customer> Customers{ get; set; }
}

Customise Asp.Net Core ApiAuthorizationDbContext table names

I'm working with Asp.Net Core identity, and I want to change the tables names that are generated by the default ApiAuthorizationDbContext. For the sake of argument, let's say that I want to change AspNetRoleClaims to be MyRoleClaims.
My DbContext looks like this:
public class MyDbContext : ApiAuthorizationDbContext<ApplicationUser>
{
public MyDbContext(
DbContextOptions<MyDbContext> options,
IOptions<OperationalStoreOptions> operationalStoreOptions)
: base(options, operationalStoreOptions)
{
}
public DbSet<MyData> MyData { get; set; }
}
I'm aware that if I inherit directly from IdentityDbContext then I can specify certain entities, but I can't see a way to do that using ApiAuthorizationDbContext. It appears that the only difference between the two are the following tables:
public DbSet<PersistedGrant> PersistedGrants { get; set; }
public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }
So, I suppose I could create my DbContext based on IdentityDbContext, and add these manually, but that feels like I'm re-inventing the wheel. Is there a way to specify these table names, or do I really need to build this manually from IdentityDbContext?
Override OnModelCreating in your ApiAuthorizationDbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>().ToTable("User");
modelBuilder.Entity<IdentityRole>().ToTable("Role");
modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole");
modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaim");
modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogin");
}

Entity Framework entity can't be found in dbcontext auto-generated code

I use entity framework 6.1.3 model first approach.
I needed to design a simple model as following.
Then i generated sql to create the database but i found that my entities sets were not defined in my DbContext. I tried to add them manually but Entity Framework keeps regenerating the following code.
It only generates the abstract entity which is exactly the opposite of what it is designed for.
public partial class UploadsDataModelContainer : DbContext
{
public UploadsDataModelContainer()
: base("name=UploadsDataModelContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<AzureBlobs> AzureBlobs { get; set; }
}
Is this a bug in EF code generator or am i missing a step in model creation ?
Thanks to RicardoPeres i added a class file with the following content and it resolved my problem by avoiding the automatic updates of the DbContext.cs file :
public partial class UploadsDataModelContainer : DbContext
{
public virtual DbSet<Chunk> CHunks { get; set; }
public virtual DbSet<Upload> Uploads { get; set; }
}

Code-first: Mapping entities to existing database tables

I am using Entity Framework 6 code-first with an existing database, but having problems mapping my entities to the database tables.
Normally, I would use database-first approach and have my entity and context code generated, but using the designer has become a huge pain.
I have set Database.SetInitializer(null) as I do not want EF to change my schema.
Database schema:
Code-first:
public class Project
{
public int ProjectId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class ReleaseControlContext : DbContext
{
public ReleaseControlContext()
: base(ConfigurationManager.ConnectionStrings["ReleaseControl"].ConnectionString)
{
Database.SetInitializer<ReleaseControlContext>(null);
}
public DbSet<Project> Projects { get; set; }
}
Calling code:
using(var context = new ReleaseControlContext())
{
var projects = context.Projects.ToList();
}
The following exception is thrown:
SqlException: Invalid object name 'dbo.Projects'.
This is because my database table is Project and not Projects. I don't want to rename my context's DbSet<Project> to "Project" because that would be semantically incorrect.
Question:
Do I have to use the fluent API/data annotations to map between the Project database table and the DbSet<Project> Projects collection?
You can use the
[Table("Project")]
public class Project {
....
}
annotation against the Project entity, or in the OnModelCreating(DbModelBuilder modelBuilder) you can call modelBuilder.Entity<Project>().ToTable("Project");.
Both would do the same thing.
You should define a class (ie:ProjectMap) that inherits from the generic class EntityTypeConfiguration(T) where T is here your Project class.
In this ProjectMap class, you can define explicitly a table mapping :
this.ToTable("Project", "dbo");
The class ProjectMap should be called in the following method of your DbContext class
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ProjectMap());
}

Entity Framework 4.1 RC: Code First EntityTypeConfiguration inheritance issue

I am trying to use a common EntityTypeConfiguration class to configure the primary key for all of my entities, so that each derived configuration class does not repeat itself. All of my entities implement a common interface IEntity (which says that each entity must have an Id property of type int).
My configuration base class looks like this:
public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity : class , IEntity {
public EntityConfiguration() {
HasKey( e => e.Id );
Property( e => e.Id ).HasDatabaseGeneratedOption( DatabaseGeneratedOption.Identity );
}
}
Each entity then has it's own specific configuration class extending this one like this:
public class CustomerConfiguration : EntityConfiguration<Customer> {
public CustomerConfiguration() : base() {
// Entity specific configuration here
}
}
It compiles fine, but the problem I am having is that at runtime I get the following Exception being raised when EF 4.1 RC tries to create the model:
System.InvalidOperationException was
unhandled Message=The key component
'Id' is not a declared property on
type 'Customer'. Verify that it has
not been explicitly excluded from the
model and that it is a valid primitive
property. Source=EntityFramework
If I change the CustomerConfiguration class to extend from EntityTypeConfiguration<Customer> and repeat the primary key configuration then it works fine, but I lose the ability to share common configuration (DRY principal is the motivation).
Am I doing something wrong here?
Is there another way to share common configuration between entities?
For reference here are the other classes involved:
public interface IEntity {
int Id { get; set; }
}
public class Customer : IEntity {
public virtual int Id { get; set; }
public virtual string name { get; set; }
}
Thanks!
It looks like these configurations has some problem with interface. It works if you change IEntity to EntityBase:
public class EntityBase
{
public virtual int Id { get; set; }
}
public class Customer : EntityBase
{
public virtual string Name { get; set; }
}
public class EntityConfiguration<TEntity> : EntityTypeConfiguration<TEntity>
where TEntity : EntityBase
{
public EntityConfiguration()
{
HasKey(e => e.Id);
Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class CustomerConfiguration : EntityConfiguration<Customer>
{
public CustomerConfiguration()
: base()
{
...
}
}
I do not think that you need to go through all of this. EF 4.1 Code First uses a lot of convention over configuration and via this, the Id property of an entity is configured as the primary key. So by implementing the IEntity interface on your entities you are setting them up with the Id as the primary key.
Here is a link to the ADO.NET Team Blog that explains how the primary key convention works - Conventions for Code First
You could just create a static method on a class and pass the entity into it. For example:
public class CustomerConfiguration : EntityConfiguration<Customer>
{
public CustomerConfiguration()
: base()
{
...
EntityConfiguration.Configure(this);
}
}
public static class EntityConfiguration
{
public static void Configure<TEntity>(EntityTypeConfiguration<TEntity> entity) where TEntity : EntityBase
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
I have similar issue with EF5.0 when i have generic abstract class with Id property and implementation for abstract members and self defined properties.
look like entity framework code first is looking only for mapped class properties.
i have tried to use reflector - seems i am right, but don't sure about this for 100%.
And, fortunately, have found solution for this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Entity<MyEntity>()
.Map(m =>
{
**m.MapInheritedProperties();**
});
}
so in my case: to map also properties from base class i have to add one line of code m.MapInheritedProperties()...

Categories