ASP .NET Core 2.1 Identity: UserRoles is null - razor

In my Razor web app, I've tried to get a list of users and their roles the following ways:
_userManager.GetUsersInRoleAsync(role).Result;
_dbContext.Users.Include(u => u.UserRoles).ThenInclude(u => u.Role);
_userManager.Users.Include(u => u.UserRoles).ThenInclude(ur => ur.Role).ToList();
And UserRoles is always null. Any idea what I'm doing wrong?
Here is my Startup:
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddDefaultUI()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();
Here is my model:
public class ApplicationUser : IdentityUser
{
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationRole : IdentityRole
{
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationUserRole : IdentityUserRole<string>
{
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
Here is my OnModelCreating:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(au =>
{
au.HasMany(e => e.UserRoles).WithOne(e => e.User).HasForeignKey(ur => ur.UserId).IsRequired();
});
builder.Entity<ApplicationRole>(ar =>
{
ar.HasMany(e => e.UserRoles).WithOne(e => e.Role).HasForeignKey(ur => ur.RoleId).IsRequired();
});
builder.Entity<ApplicationUserRole>(aur =>
{
aur.HasOne(ur => ur.Role).WithMany(r => r.UserRoles).HasForeignKey(ur => ur.RoleId).IsRequired();
aur.HasOne(ur => ur.User).WithMany(r => r.UserRoles).HasForeignKey(ur => ur.UserId).IsRequired();
});
}

Related

Entity FrameWork lazy loading 0 to many fluent api mapping issue

I been breaking my head for hours trying to find out why my navigation property is coming back null for 0 to many scenario. For 1 to 1 it works just fine.
These are my entities:
public class Barber: BaseEntity
{
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public int? AppointmentId { get; set; }
public int? UserId { get; set; }
public virtual ICollection<Users> Users { get; set; }
public Barber()
{
}
}
public class Users: BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public bool IsBarber { get; set; }
public int? BarberId { get; set; }
public string FacebookToken { get; set; }
public DateTime? CreatedOn { get; set;}
public virtual Barber Barber { get; set; }
/// <summary>
/// default constructor
/// </summary>
public Users() { }
}
my mapping is as follow:
for Barber:
public BarberMapping()
{
ToTable("Barber");
HasKey(p => p.Id);
Property(p => p.Street1).HasColumnName("Street1");
Property(p => p.Street2).HasColumnName("Street2");
Property(p => p.City).HasColumnName("City");
Property(p => p.State).HasColumnName("State");
Property(p => p.PostalCode).HasColumnName("PostalCode");
Property(p => p.AppointmentId).HasColumnName("AppointmentId");
Property(p => p.UserId).HasColumnName("UserId");
HasOptional(p => p.Users)
.WithMany()
.HasForeignKey(p => p.UserId);
}
}
for User:
public UserMapping()
{
ToTable("Users");
HasKey(p => p.Id);
Property(p => p.FirstName);
Property(p => p.LastName );
Property(p => p.Password);
Property(p => p.Email);
Property(p => p.CreatedOn);
Property(p => p.FacebookToken);
Property(p => p.IsBarber);
}
Finally i'm calling my data like this:
_userRepository.All.Where(p => p.Id == id).Include(p => p.Barber).FirstOrDefault();
When the query comes back I get everything except the Barber property which comes back as null. Anything i'm missing to make this relationShip work?
I'm using EF 6.1.3 with mySQL 6.9 on visual studio for mac.

Issue with Many-To-Many relationships in MySql

I am using EF Core with MySQL using SapientGuardian's EFCore library and I am trying to create a table with many-to-many relationship using the following code;
public class Personnel
{
public int Id { get; set; }
[MaxLength(100)]
public string Name { get; set; }
public virtual ICollection<PersonnelDegree> PersonnelDegrees { get; set; }
}
public class Degree
{
public int Id { get; set; }
[MaxLength(100)]
public string Name { get; set; }
public virtual ICollection<PersonnelDegree> PersonnelDegrees { get; set; }
}
public class PersonnelDegree
{
public int PersonnelId { get; set; }
public int DegreeId { get; set; }
public virtual Personnel Personnel { get; set; }
public virtual Degree Degree { get; set; }
}
// Inside the OnModelCreating override
builder.Entity<Degree>().HasMany(x => x.Personnel);
builder.Entity<Personnel>().HasMany(x => x.Degrees);
builder.Entity<PersonnelDegree>()
.HasKey(x => new { x.DegreeId, x.PersonnelId });
builder.Entity<PersonnelDegree>()
.HasOne(x => x.Degree)
.WithMany(x => x.PersonnelDegrees)
.HasForeignKey(x => x.DegreeId);
builder.Entity<PersonnelDegree>()
.HasOne(x => x.Personnel)
.WithMany(x => x.PersonnelDegrees)
.HasForeignKey(x => x.PersonnelId);
Now, when I run dotnet ef migration add personnel; I get this...
migrationBuilder.CreateTable(
name: "Role",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("MySQL:AutoIncrement", true),
ApplicationId = table.Column<int>(nullable: true),
Name = table.Column<string>(maxLength: 100, nullable: true),
PersonnelId = table.Column<int>(nullable: true) // Where is this coming from?
},
constraints: table =>
{
table.PrimaryKey("PK_Role", x => x.Id);
table.ForeignKey(
name: "FK_Role_Application_ApplicationId",
column: x => x.ApplicationId,
principalTable: "Application",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
Notice that the table definition has for Role has PersonnelId column in it. And Personnel table has RoleId? Can anybody tell me what is going on here?
I have the same models, but different OnModelCreating method.
So I assume that you configured something wrong. It should be something like this for your case:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<PersonnelDegree>()
.HasKey(t => new { t.PersonnelId , t.DegreeId });
}
That is all you should have in your OnModelCreating method.

The underlying provider does not support the type 'datetimeoffset'

I'm trying to integrate my API, using EF6, with MySQL.
I've installed the package MySql.Data.Entity (version 6.9.7).
Initially, I used Sql Server, so my mapping for date fields used the type DateTimeOffSet. But, when using MySql, I had troubles with that type, so I changed it to DateTime. The migration runs successfully, creates the database in MySql, but in the end of the log shows an error:
PM> Update-Database -StartUpProjectName WMoney.WebApi -Verbose
Using StartUp project 'WMoney.WebApi'.
Using NuGet project 'WMoney.Persistence.EntityFramework'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'wmoney' (DataSource: localhost, Provider: MySql.Data.MySqlClient, Origin: Configuration).
No pending explicit migrations.
System.ArgumentException: The underlying provider does not support the type 'datetimeoffset'.
at MySql.Data.MySqlClient.MySqlProviderManifest.GetEdmType(TypeUsage storeType)
at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.BuildColumnModel(EdmProperty property, ModelMetadata modelMetadata, IDictionary`2 annotations)
at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.BuildAlterColumnOperation(String table, EdmProperty targetProperty, ModelMetadata targetModelMetadata, EdmProperty sourceProperty, ModelMetadata sourceModelMetadata)
at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.<FindAlteredColumns>b__24a(<>f__AnonymousType2c`2 <>h__TransparentIdentifier242)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff(ModelMetadata source, ModelMetadata target, Lazy`1 modificationCommandTreeGenerator, MigrationSqlGenerator migrationSqlGenerator, String sourceModelVersion, String targetModelVersion)
at System.Data.Entity.Migrations.Infrastructure.EdmModelDiffer.Diff(XDocument sourceModel, XDocument targetModel, Lazy`1 modificationCommandTreeGenerator, MigrationSqlGenerator migrationSqlGenerator, String sourceModelVersion, String targetModelVersion)
at System.Data.Entity.Migrations.DbMigrator.IsModelOutOfDate(XDocument model, DbMigration lastMigration)
at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
The underlying provider does not support the type 'datetimeoffset'.
Besides the error, the database is created, and I can run my Api. But, when trying to make a query on DB the same error occurs: "The underlying provider does not support the type 'datetimeoffset'."
I already changed all references to DateTimeOffSet from my code, but the error still happenning.
Does anyone have any idea what can I do to solve this problem?
Thanks
UPDATE:
As requested by DevilSuichiro, I'm adding more informations:
MY CONTEXT CLASS:
namespace WMoney.Persistence.EntityFramework
{
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class WMoneyContext : DbContext, IWMoneyContext
{
public WMoneyContext()
: base("WMoneyConnectionString")
{
}
public IUserRepository UserRepository
{
get { return new UserRepository(this); }
}
public DbSet<Account> Accounts { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Transaction> Transactions { get; set; }
public DbSet<TransactionType> TransactionTypes { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Account>()
.HasKey(a => a.AccountId)
.Map(a => a.ToTable("TbAccount", "dbo"));
modelBuilder.Entity<Account>()
.HasRequired(a => a.User)
.WithMany(a => a.Accounts)
.HasForeignKey(a => a.UserId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Category>()
.HasKey(a => a.CategoryId)
.Map(a => a.ToTable("TbCategory", "dbo"));
modelBuilder.Entity<Category>()
.HasRequired(a => a.User)
.WithMany(a => a.Categories)
.HasForeignKey(a => a.UserId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Transaction>()
.HasKey(a => a.TransactionId)
.Map(a => a.ToTable("TbTransaction", "dbo"));
modelBuilder.Entity<Transaction>()
.HasRequired(a => a.Account)
.WithMany(a => a.Transactions)
.HasForeignKey(a => a.AccountId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Transaction>()
.HasRequired(a => a.Category)
.WithMany(a => a.Transactions)
.HasForeignKey(a => a.CategoryId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Transaction>()
.HasRequired(a => a.TransactionType)
.WithMany(a => a.Transactions)
.HasForeignKey(a => a.TransactionTypeId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<TransactionType>()
.HasKey(a => a.TransactionTypeId)
.Map(a => a.ToTable("TbTransactionType", "dbo"));
modelBuilder.Entity<User>()
.HasKey(a => a.UserId)
.Map(a => a.ToTable("TbUser", "dbo"));
}
}
}
MY TRANSACTION CLASS (The only with date fields)
namespace WMoney.Persistence.Model
{
public class Transaction
{
public int TransactionId { get; set; }
public int TransactionTypeId { get; set; }
public DateTime Created { get; set; }
public DateTime Date { get; set; }
public int CategoryId { get; set; }
public int AccountId { get; set; }
public decimal Value { get; set; }
[StringLength(200)]
public string Description { get; set; }
public virtual TransactionType TransactionType { get; set; }
public virtual Category Category { get; set; }
public virtual Account Account { get; set; }
}
}
MY CLASS WHO CALLS THE DATABASE
The error happens already in the line:
var existentUser = await _userRepository.AsQueryable().GetByEmail(email);
namespace WMoney.Core
{
public class UserCore : IUserCore
{
public IUserRepository _userRepository;
public UserCore(IWMoneyContext wMoneyContext)
{
_userRepository = wMoneyContext.UserRepository;
}
public async Task<User> CreateUserAsync(string email, string password)
{
var existentUser = await _userRepository.AsQueryable().GetByEmail(email);
if (existentUser != null)
{
throw new DuplicateWaitObjectException();
}
var user = new User
{
Email = email,
Password = password
};
await _userRepository.AddAsync(user, true);
return user;
}
public async Task<bool> CheckUserAsync(string email, string password)
{
var user = await _userRepository.AsQueryable().GetByEmail(email);
if (user != null)
{
if (user.Password == password)
{
return true;
}
else
{
return false;
}
}
else
{
throw new ArgumentException(string.Format("There's no user with email '{0}'", email));
}
}
}
}

Entity Framewrok 5 fluent mapping for many to many with 3 entities

I have the following scenario that is giving me a hard time:
public class SegUser
{
public string IdUser { get; set; }
public List<SegRol> SegRoles { get; set; }
public virtual List<SegApps> Apps{ get; set; }
}
public class SegRole
{
public virtual int IdRole { get; set; }
public virtual List<SegUer> SegUsers { get; set; }
public virtual List<SegApp> Apps { get; set; }
}
public class SegApp
{
public virtual int IdApp{ get; set; }
public virtual List<SegUser> Users { get; set; }
public virtual List<SegRole> Roles { get; set; }
}
In my database I have those 3 tables and an extra table with 3 PKs (one for each entity) to establish the relationship between those 3 entities.
How can I achieve the mapping with Entity Framework 5 fluent API.
I've already tried:
private void MapSegUser()
{
//mapping of another fields
entityConfiguration
.HasMany(x => x.SegRoles)
.WithMany(x => x.SegUsers)
.Map(mc =>
{
mc.MapLeftKey("id_role");
mc.MapRightKey("id_user");
mc.ToTable("seg_users_roles");
});
entityConfiguration
.HasMany(x => x.Apps)
.WithMany(x => x.Users)
.Map(mc =>
{
mc.MapLeftKey("id_app");
mc.MapRightKey("id_user");
mc.ToTable("seg_users_roles_apps");
});
}
private void MapSegApp()
{
//mapping of another fields
entityConfiguration
.HasMany(x => x.Users)
.WithMany(x => x.Apps)
.Map(mc =>
{
mc.MapLeftKey("id_user");
mc.MapRightKey("id_app");
mc.ToTable("seg_users_roles_apps");
});
}
private void MapSegRole()
{
//mapping of another fields
entityConfiguration
.HasMany(x => x.SegUsers)
.WithMany(x => x.SegRoles)
.Map(mc =>
{
mc.MapLeftKey("id_user");
mc.MapRightKey("id_role");
mc.ToTable("seg_users_roles");
});
}

error 0019: Each property name in a type must be unique on ID field

ANSWERED! (will be posting it shortly. I seriously think it's a bug in EF.)
I have the following set of (code-first) classes which will be the future of the application as we are replacing the old (gen'd from db). The dbcontext, two mappings/configurations, two POCOs, and a base class.
In addition to this in another project entirely is an edmx generated from the database. Up until now, there have not been any issues with the two conflicting. There are several other unrelated sets in the context (not shown,) but it wasn't until I started trying to get the relationship between SalesReps and SalesGroups that I started having issues. Commenting out adding the SalesGroupMapping in OnModelCreating will allow it to run.
The Error:
Schema specified is not valid. Errors:
(19,6) : error 0019: Each property name in a type must be unique. Property name 'PKID_MasterRepGroup' was already defined.
(27,6) : error 0019: Each property name in a type must be unique. Property name 'PKID_MasterRepGroup' was already defined.
The Code:
public class MyDbContext{
public IDbSet<SalesGroup> SalesGroups { get; set; }
public IDbSet<SalesRep> SalesReps { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new InsuranceProviderMapping());
modelBuilder.Configurations.Add(new SalesGroupMapping());
modelBuilder.Configurations.Add(new SalesRepMapping());
base.OnModelCreating(modelBuilder);
}
}
class SalesRepMapping : EntityTypeConfiguration<SalesRep>
{
public SalesRepMapping()
{
ToTable("SalesRep");
Property(p => p.Id).HasColumnName("PKID_SalesRep");
Property(p => p.Email).HasColumnName("EMailAddress1");
Property(p => p.Address.Address1).HasColumnName("Address");
Property(p => p.Address.Address2).HasColumnName("Address2");
Property(p => p.Address.City).HasColumnName("City");
Property(p => p.Address.State).HasColumnName("State");
Property(p => p.Address.Zipcode).HasColumnName("Zipcode");
//Property(p => p.SalesGroupId).HasColumnName("FK_MasterRepGroup");
//HasRequired(p => p.SalesGroup).WithMany(c => c.SalesReps).HasForeignKey(b => b.SalesGroupId);
//Note: dropping emailaddress2
}
}
class SalesGroupMapping : EntityTypeConfiguration<SalesGroup>
{
public SalesGroupMapping()
{
ToTable("MasterRepGroup");
Property(p => p.Id).HasColumnName("PKID_MasterRepGroup");
Property(p => p.Name).HasColumnName("CompanyName");
Property(p => p.PrimaryContact.FirstName).HasColumnName("Contact1FirstName");
Property(p => p.PrimaryContact.LastName).HasColumnName("Contact1LastName");
Property(p => p.PrimaryContact.Phone).HasColumnName("Contact1Phone");
Property(p => p.PrimaryContact.Fax).HasColumnName("Contact1Fax");
Property(p => p.PrimaryContact.Email).HasColumnName("Contact1EMail");
Property(p => p.SecondaryContact.FirstName).HasColumnName("Contact2FirstName");
Property(p => p.SecondaryContact.LastName).HasColumnName("Contact2LastName");
Property(p => p.SecondaryContact.Phone).HasColumnName("Contact2Phone");
Property(p => p.SecondaryContact.Fax).HasColumnName("Contact2Fax");
Property(p => p.SecondaryContact.Email).HasColumnName("Contact2EMail");
Property(p => p.Address.Address1).HasColumnName("Address");
Property(p => p.Address.Address2).HasColumnName("Address2");
Property(p => p.Address.City).HasColumnName("City");
Property(p => p.Address.State).HasColumnName("State");
Property(p => p.Address.Zipcode).HasColumnName("Zipcode");
}
}
public class SalesRep: Entity
{
virtual public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Phone]
virtual public string Phone { get; set; }
[Phone]
virtual public string Fax { get; set; }
[Email]
virtual public string Email { get; set; }
virtual public string Notes { get; set; }
virtual public Address Address { get; set; }
//public long SalesGroupId { get; set; }
//[Required]
////[ForeignKey("SalesGroupId")]
//virtual public SalesGroup SalesGroup { get; set; }
}
public class SalesGroup : Entity
{
public SalesGroup()
{
//SalesReps = new List<SalesRep>();
}
[Required]
public string Name { get; set; }
virtual public Address Address { get; set; }
virtual public Contact PrimaryContact { get; set; }
virtual public Contact SecondaryContact { get; set; }
//virtual public ICollection<SalesRep> SalesReps {get; set;}
}
public abstract class Entity : NMTC.Core.DataContracts.IEntity
{
// TODO database columns will eventually be int instead of bigint
public long Id { get; set; }
}
}
Any ideas? I've been banging my head on this one since Friday. If you know of a way I can track down what it's thinking, that would help, too.
Much appreciated.
More Info:
Commenting out the mapping for the Id property alone will allow the model to be created. That won't actually help long-term, though.
The error is a problem with EF.
In the mapping, I map Property(p=>p.Id).HasColumnName("MyId");
In my Contact class, which inherits from my Entity class, there are also IDs.
Because I did not explicitly map these columns, the mapping "trickled down" and was trying to map my Contact.Id properties in the same fashion.
Solutions:
a) Map them explicitly
b) Remove the inheritance so that Contact isn't of type Entity and is instead a ComplexType (doesn't have an ID.)