Create the relationship table between 2 tables in asp.net mvc EF - c#

I created:
custom custom membership provider
custom role provider
an user model
an role model
It create me the 2 custom tables correctly.
Now I want to create the table between Users and Roles with 2 columns: RoleId, UserId
I should I tweak my models to teach to EF to create this relationship table (UsersInRole)?
User model:
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public Int32 CompanyId { get; set; }
[Required]
public String UserName { get; set; }
public String Password { get; set; }
public String PasswordSalt { get; set; }
public String Email { get; set; }
public Boolean IsApproved { get; set; }
public Boolean IsLockedOut { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangedDate { get; set; }
public DateTime LastLockoutDate { get; set; }
}
Role model:
public class Role
{
[Key]
public int RoleId { get; set; }
[Required]
[MaxLength(20)]
public string Name { get; set; }
public ICollection<string> AssignedUsers { get; set; }
}

If you are using code-first EF, then all you should need to do is add a collection of the Users to the Role class and vice-versa. EF takes this two-way link as a signal to create a many-to-many relationship in the underlying data store. To summarize, your classes would be augmented something like this...
public class User
{
...
List<Role> Roles {get; set;}
}
public class Role
{
...
List<User> Users {get; set;}
}

public class Role
{
[Key]
public int RoleId { get; set; }
[Required]
[MaxLength(20)]
public string Name { get; set; }
public ICollection<User> AssignedUsers { get; set; }
}
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public Int32 CompanyId { get; set; }
[Required]
public String UserName { get; set; }
public String Password { get; set; }
public String PasswordSalt { get; set; }
public String Email { get; set; }
public Boolean IsApproved { get; set; }
public Boolean IsLockedOut { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastPasswordChangedDate { get; set; }
public DateTime LastLockoutDate { get; set; }
public ICollection<Role> Roles{ get; set; }
}

Related

How add identity and user management into aspnetcore web api?

I'm building asp.net core web api with 3 types of users: Admin, Clients and Programmers. Each of those roles have their own list of tickets. These are entity classes I've already added:
public class User
{
[Key]
public Guid Id { get; set; }
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string Zip { get; set; }
[Required]
[Phone]
public string PhoneNumber { get; set; }
[Required]
[EmailAddress]
public string EmailAddress { get; set; }
[Required]
public Gender Gender { get; set; }
[Required]
[MaxLength(50)]
public string UserName { get; set; }
[Required]
[MaxLength(50)]
public string Password { get; set; }
[Required]
public Role Role { get; set; }
public virtual Programmer Programmer { get; set; }
public virtual Admin Admin { get; set; }
public virtual Client Client { get; set; }
}
public class Client
{
public Guid clientId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; } = new List<Ticket>();
public Guid Id { get; set; }
public virtual User User { get; set; }
}
public class Admin
{
public Guid adminId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; } = new List<Ticket>();
public Guid Id { get; set; }
public virtual User User { get; set; }
}
public class Programmer
{
public Guid programmerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ProgrammingLanguage ProgrammingLanguage { get; set; }
public Experience Experience { get; set; }
public DetailOriented DetailOriented { get; set; }
public FieldOfInterest FieldOfInterest { get; set; }
public virtual ICollection<Ticket> Tickets { get; set; } = new List<Ticket>();
public Guid Id { get; set; }
public virtual User User { get; set; }
}
I've already created regular DbContext and implemented functionality of my api using that DbContext. Now I want to change users to be IdentityUsers. I'm not sure should I make a new project where UserIdentity will be handled and then pass those users to my api(if so, how can I pass them to api and connect them with their tickets, i.e.do I leave only tickets table in api?) or make users as part of an api as I already did(if so, what would be the best way to change them into identity users so that I can query their tickets later?). Does anyone have any tips/links/similar code samples or something? I would be grateful :)
Out of the box, Identity supports a single set of user profile properties. The easiest solution would be to create an AppUser class that inherits from IdentityUser with ALL of the properties across your user types. Also introduce an interface for each of your user types with the properties they support.
class AppUser: IdentityUser, IAdmin, IProgrammmer, IClient {...}
Based on the IdentityRole associated with the user, you can cast the AppUser instance to the appropriate interface to access the user-specific properties.

How should I create this relationship in Entity Framework?

In my previous question, I've mentioned that I'm developing a Point of Sale application. The platforms I use are WPF, MVVM and Entity Framework (code-first). Since Entity Framework code-first has its own logic to map entities and relations, I'm confused about a case.
I have an EntityBase class:
public class EntityBase
{
public DateTime? CreatedAt { get; set; }
public User CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public User UpdatedBy { get; set; }
}
public class User : EntityBase
{
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Since User class has EntityBase class members, will it arise problems at database side?
Or should I keep the data like this:
public class EntityBase
{
public DateTime? CreatedAt { get; set; }
public int CreatedByUserId { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UpdatedByUserId { get; set; }
}
Create your models in this way:
public class EntityBase
{
public DateTime? CreatedAt { get; set; }
public int CreatedById { get; set; }
[ForeignKey("CreatedById")]
public User CreatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UpdatedById { get; set; }
[ForeignKey("UpdatedById")]
public User UpdatedBy { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}

SQL Exception trying to add an existing user when context.SaveChanges() on a different table

I am trying to add an entry to a table that holds a users browsing history information. However, when trying to save the addition an SqlException is thrown:
Cannot insert duplicate key row in object 'dbo.AspNetUsers' with
unique index 'UserNameIndex'. The duplicate key value is
(exampleUserName). The statement has been terminated.
A user is has many browsing histories but a browsing history can only be attached to one user so there is a user as part of the BrowsingHistory DataModel:
namespace DataModels
{
[Table("BrowsingHistory")]
public class BrowsingHistory
{
[Key]
public int BrowsingHistoryId { get; set; }
public int ProductId { get; set; }
public System.DateTime DateTime { get; set; }
public int DeviceId { get; set; }
public int UserId { get; set; }
public virtual AspNetUsers User { get; set; }
public virtual Device Device { get; set; }
public virtual Product Product { get; set; }
}
}
It is to note that I am using the Microsoft Identity classes for my authentication. The user class looks as follows:
namespace DataModels
{
using System;
using System.Collections.Generic;
[Table("AspNetUsers")]
public class AspNetUsers
{
public AspNetUsers()
{
BrowsingHistories = new HashSet<BrowsingHistory>();
Orders = new HashSet<Order>();
AspNetUserClaims = new HashSet<AspNetUserClaims>();
AspNetRoles = new HashSet<AspNetRoles>();
}
[Key]
public int Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTime? LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string HouseName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
public string ContactNumber { get; set; }
public virtual ICollection<BrowsingHistory> BrowsingHistories { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual ShoppingCart ShoppingCart { get; set; }
public virtual ICollection<AspNetUserClaims> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetRoles> AspNetRoles { get; set; }
}
}
The error occurs when trying to save the addition in the repository. On the _context.SaveChanges() line the method below.
public void CreateBrowsingHistoryEntry(BrowsingHistory bhe)
{
_context.BrowsingHistory.Add(bhe);
_context.SaveChanges();
}
Any help with this issue would be greatly appreciated.

Invalid column name when inserting - Entity Framework

I'm using Entity framework using code first. I have 3 tables in database:
Place
Profil
PlaceMember
It's a many to many relation. A place can have many Profils as members and a profil can be a member to many Places. The PlaceMember is the relational table.
Code of PlaceDTO:
[Table("Place")]
public partial class PlaceDTO
{
public PlaceDTO()
{
Members = new HashSet<ProfilDTO>();
}
public int id { get; set; }
[StringLength(100)]
public string description { get; set; }
public DateTime dateOut { get; set; }
public DateTime createDate { get; set; }
public int? canceled { get; set; }
public int profilId { get; set; }
public int addressId { get; set; }
public virtual AddressDTO Address { get; set; }
public virtual ProfilDTO Profil { get; set; }
public virtual ICollection<ProfilDTO> Members { get; set; }
}
Code of Profil class:
public partial class ProfilDTO
{
public ProfilDTO()
{
Devices = new HashSet<DeviceDTO>();
Notifications = new HashSet<NotificationDTO>();
Places = new HashSet<PlaceDTO>();
}
public int id { get; set; }
[Required]
[StringLength(50)]
public string pseudo { get; set; }
[Required]
[StringLength(50)]
public string firstname { get; set; }
[Required]
[StringLength(50)]
public string lastname { get; set; }
[Required]
[StringLength(15)]
public string phone { get; set; }
[Required]
[StringLength(50)]
public string emailAdresse { get; set; }
[Required]
[StringLength(150)]
public string password { get; set; }
public DateTime lastUpdatePassword { get; set; }
public DateTime lastUpdateProfil { get; set; }
public DateTime createDate { get; set; }
public byte[] picture { get; set; }
public virtual ICollection<PlaceDTO> Places { get; set; }
}
Code of PlaceMember class:
[Table("PlaceMember")]
public partial class PlaceMemberDTO
{
[Key]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int placeId { get; set; }
[Key]
[Column(Order = 1)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int invitedId { get; set; }
}
In database, the placeId and invitedId are both identity key of the table.
When I'm trying to add a new place to the Place table, I'm getting that PlaceDTO_id is not a valid column name despite the fact that the place table in database has an column named id and is the identity column.
context.Address.Attach(place.Address);
context.Address.Add(place.Address);
place.addressId = place.Address.id;
context.Places.Attach(place);
context.Places.Add(place);
context.SaveChanges();
The place object, put in param, contains 3 members that exists in Profil table.
When I remove the Members field from the PlaceDTO table, the place is inserted but nothing added to the PlaceMember table.
What's wrong ?

How to join Aspnet_User to my custom user

I have a User model object and I wan't to when I get this object to get aspnet_User object with it for additional data (usename etc.)
public class User
{
public Guid UserId_fk { get; set; }
public int UserId { get; set; }
public string FirstName { get; set; }
public virtual AspnetUsers AspnetUsers { get; set; }
}
public class AspnetUsers
{
public Guid ApplicationId { get; set; }
public Guid UserId { get; set; }
public string UserName { get; set; }
public string LoweredUserName { get; set; }
public string MobileAlias { get; set; }
public bool IsAnonymous { get; set; }
public DateTime LastActivityDate { get; set; }
}
In database UserId_fk is FK to aspnet_Users.UserId.
How to map this?

Categories