Cannot migrate AspNetUser entity in Entity Framework Code First Approach in .NET - asp.net

I am developing an ASP.NET MVC project using Visual Studio 2013. I am using Entity Framework Code First Approach to interact with database. But I am having a problem with migrating data because of built-in identity system in ASP.NET. Everything was fine before I touch to identity system.
These are the steps I have done.
I registered an account from UI using built-in identity system. So AspNetUsers table is created in database.
I created AspNetUser class to my code because I need to work with it.
Then I run migration and update database command. It throws error.
This is my AspNetUser class
public class AspNetUser
{
[Required]
public String Id { get; set; }
[Required]
public String UserName { get; set; }
public String PasswordHash { get; set; }
public String SecurityStamp { get; set; }
[Required]
public String Discriminator { get; set; }
}
This is my db context class
public class AyarDbContext : DbContext
{
public AyarDbContext()
: base("DefaultConnection")
{
}
public DbSet<Category> Categories { get; set; }
public DbSet<Region> Regions { get; set; }
public DbSet<Area> Areas { get; set; }
public DbSet<Item> Items { get; set; }
public DbSet<ItemContactInfo> ItemContacts { get; set; }
public DbSet<Gallery> Galleries { get; set; }
public DbSet<Mail> Mails { get; set; }
public DbSet<AspNetUser> AspNetUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
This is the error I got.
There is already an object named 'AspNetUsers' in the database.
How can I migrate AspNetUser class? I registered using UI because I auto create the other tables need for identity system. How can I migrate that class and map with AspNetUsers table that is already existing in database.

As the error explains, that table already exists and is accessible in this way:
var user = context.Users.First(u => u.Id == myId);
If you want to extend the user class and add properties, you can inherit it:
public class MyAppUser : IdentityUser
{
// don't include properties already in IdentityUser
public string MyNewProperty { get; set; }
}
http://johnatten.com/2014/06/22/asp-net-identity-2-0-customizing-users-and-roles/

Related

EF Core one-to-many relationship with multiple contexts (databases)

I have contexts with entities like this:
public class CompanyContext : DbContext
{
public DbSet<StoreModel> Stores { get; set; }
// Other entities
}
public class DepartmentContext : DbContext
{
public DbSet<OrderModel> Orders { get; set; }
// Other entities
}
public class StoreModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<OrderModel> ReceivedOrders { get; set; }
public virtual ICollection<OrderModel> PreparedOrders { get; set; }
public virtual ICollection<OrderModel> IssuedOrders { get; set; }
}
public class OrderModel
{
public Guid Id { get; set; }
public string Details { get; set; }
public StoreModel GettingStore { get; set; }
public StoreModel PreparingStore { get; set; }
public StoreModel IssuanceStore { get; set; }
}
For example a user makes an order in storeA, but wants to receive it in storeC, and it order will preparing in storeB. And I needs a statiscics about store received/prepared/issued orders.
When I try to create a migrations, EF throws exceptions "Unable to determine the relationship represented by navigation 'OrderModel.GettingStore' of type 'StoreModel'" and "Unable to determine the relationship represented by navigation 'StoreModel.IssuedOrders' of type 'ICollection<OrderModel>'". If I understand correctly, this happens because entities are defined in different contexts.
Now I just use next model:
public class OrderModel
{
public Guid Id { get; set; }
public string Details { get; set; }
public Guid GettingStoreId { get; set; }
public Guid PreparingStoreId { get; set; }
public Guid IssuanceStoreId { get; set; }
}
This works fine, but perhaps there are options that allow to create such a structure using navigation properties, with correct relationships between these entities from different contexts(databases).
First, the map of a different database was not placed in tables of different application formats, so think that you have a domain that should be well defined in your application, that way you would have the mapping of your application like this:
public class DomainNameContext: DbContext
{
public DomainNameContext(): base()
{
}
public DbSet<StoreModel> Stores { get; set; }
public DbSet<OrderModel> Orders { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// config mapping methods
}
}
another thing, the relation you are using doesn't work so you can't have a repetition of Orders within the same class because this is not one -> many, this statement means that a StoreModel line can have many lines in the OrderModel this way would be like this
public class OrderModel
{
public Guid Id { get; set; }
public string Details { get; set; }
public Guid StoreModeId { get; set; } // this part will show the entity framework that this is the fk it will correlate
public StoreModel StoreModel { get; set; }
}
public class StoreModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<OrderModel> OrderModels { get; set; }
}
see that if you are wanting to have many StoreModel related to many OrderModel then you need to use many -> many which microsoft documentation foresees to use as well
good to map this within its context it is necessary in OnModelCreating to use its mapping like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// config mapping methods
modelBuilder.Entity<StoreModel>()
.HasMany<OrderModel>(g => g.OrderModels )
.HasForeignkey<Guid>(s => s.StoreModeId )
}
you can have a look at the microsoft documentation enter link description here, enter link description here
now if you need to map between contexts you will have to use dapper to make separate queries in separate bases the entity has support for that in this link enter link description here
and then you can make the necessary inner joins so that you can use it but natively this does not exist, I advise you to rethink your database so that it can make more sense to a relational model, perhaps putting types for your StoreModel and OrderModel so you can use the way I wanted the types GettingStore, PreparingStore, IssuanceStore using an enum for this to make it explicit

Entity Framework shows inconsistent behaviour when used with Asp.net Identity

I have 3 tables Violation,Comment and and auto generated AspNetUsers respectively.The relationship between them as follows.
I am using code-first approach and my models are as follows.Some properties are removed for brevity.
Violation Model
public class Violation
{
public Violation()
{
this.Comments = new HashSet<Comment>();
}
public int Id { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ApplicationUser CreatorUser { get; set; }
}
Comment Model
public class Comment
{
public int Id { get; set; }
[Required]
public string Content { get; set; }
[Required]
public DateTime PostedDateTime { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public Violation Violation { get; set; }
}
ApplicationUser(AspNetUsers Table)
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
this.Comments = new List<Comment>();
this.Violations = new List<Violation>();
}
public virtual List<Comment> Comments { get; set; }
public virtual List<Violation> Violations { get; set; }
}
The problem is that when I try to retrieve Comment's ApplicationUser navigation property , I see many of them pointing to a null property even database has proper record for each of them.
Shortly,EF doesn't retrieve database records properly.I stuck with it,can't find the reason.
In fact, it's not being lazy-loaded. You didn't add the virtual keyword to your Comment.ApplicationUser property, so Entity Framework cannot override it to add the lazy-loading logic. As a result, it's always going to be null unless you explicitly load it. Add the virtual keyword, and you'll be fine.
If you want the navigation properties populated you need to include them in the query:
var comments = context.Comments
.Include(c => c.Violation)
.Include(c => c.ApplicationUser)
.Where(x => x.Violation.Id == violationId);
https://msdn.microsoft.com/en-us/data/jj574232.aspx#eager

ASP.NET Identity for WebForms - getting started with extending User attributes

I'm working on my first ASP.NET WebForms project using Identity. I ticked the box when creating the project and the basics all seem to be working OK. Now I want to extend the Register form and the AspNetUsers table with new attributes (e.g. Users (actual) Name). I'd also like to expose the existing PhoneNumber attribute.
I did some research but couldn't find any non-MVC info on this scenario. Is the expectation that I just hack away at the template code to achieve this?
I'm happy to do so, just wondering if I am missing something...
As you say you are using an ASP.NET Web From with default files and folders.
Please open the IdentityMode.cs in Models folder and find ApplicationUser class.
In this class you can add user attributes as properties, see example :
01: add profile information in users table:
public class ApplicationUser : IdentityUser
{
[Required]
public string UserFullName { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string PhoneNumber { get; set; }
[Required]
public string Address { get; set; }
public DateTime RegisteredDate { get; set; }
public string Info { get; set; }
}
02 :
you can add profile information in different table :
public class ApplicationUser : IdentityUser
{
public virtual UserInfo UserInfo { get; set; }
}
public class UserInfo
{
[Required]
public string UserFullName { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string PhoneNumber { get; set; }
[Required]
public string Address { get; set; }
public DateTime RegisteredDate { get; set; }
public string Info { get; set; }
}

Using complex user type linked to existing table in the new ASP.NET Identity

I'm trying to implement new ASP.NET Identity in my old project. I have an existing table called tda_Contacts in the database. The following code works fine without table attribute and creates all new identity related tables plus TdaContacts table. But when put existing table name in the table attribute ([Table("tda_Contacts")]), then it does nothing and throws Invalid object name 'dbo.UserSecrets' exeption. Also if I put different name in that attribute it works fine and creates a correct table with exactly the same columns and types as existing tda_Contacts.
What am I doing wrong? How to force it to use my existing table?
public class IdentityUser : User
{
public int ContactID { get; set; }
[ForeignKey("ContactID ")]
public virtual TdaContact TdaContact { get; set; }
}
public class CustomUserContext : IdentityStoreContext
{
public CustomUserContext(DbContext db) : base(db)
{
Users = new UserStore<IdentityUser>(db);
}
}
public class MyDbContext : IdentityDbContext<IdentityUser, UserClaim, UserSecret, UserLogin, Role, UserRole>
{
public MyDbContext() : base("Name=MyConnectionString")
{
}
public IDbSet<TdaContact> TdaContacts { get; set; }
}
[Table("tda_Contacts")]
public class TdaContact
{
[Key]
public int ContactID { get; set; }
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[MaxLength(255)]
public string Email { get; set; }
}
P.S. Just discovered that with precreated IdentityUsers table with correct foreign key to tda_Contacts it works as expected.

EF5 Code-First - Create new table

I'm working with asp.net mvc3 & Entity Framework5.
My database has been designed with the Code-First.
Entity Code
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class EFDbContext : DbContext
{
public DbSet<User> Users { get; set; }
}
Create DB Option
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFDbContext>());
I use this option, the database has been created.
After the database has been created, I need a Role table was.
So I had to modify the code as follows.
Entity Code
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
}
public class EFDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
}
I use Create DB Option again.
In this case, the existing Users table will be deleted after regeneration.
I would like to be added to the Role table, but leave data in the table Users.
What should I do?
Use Code-First Migrations.
Database.SetInitializer(null);
Then in Package Manager Console write:
add-migration addedRoles
If you did't enabled migrations before, You must enable it first:
enable-migrations
and last:
update-database
Complete guid:
http://msdn.microsoft.com/en-US/data/jj591621
Edit
If you want the database to be upgraded automatically whenever you run the application, you can use MigrateDatabaseToLatestVersion initializer:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<EFDbContext, Configuration>());
Learn how migrations work.
http://msdn.microsoft.com/en-us/data/jj591621.aspx
They have another initializer, MigrateDatabaseToLatestVersion. In contrast to the one you use, this one will automatically upgrade your database to latest version without recreating the whole database.

Resources