How to configure a one-to-one relationship with identity class and two db context - entity-framework

Let me try to explaine. I have 2 classes, one class called ApplicationUser that inherit from IdentityUser to insert some properties and one class called Company. I would like to create a one-to-one relationship between both to allow me to access the user and navigate to his companies. I am using 2 different dbContext, one for the identity and one for the rest of entities so i don't know how and which dbContext should i configure it. Could you please assist me?
THAT IS MY APPLICATIONUSER CLASS:
`
public class ApplicationUser : IdentityUser
{
public string Fullname { get; set; }
public override string Email { get => base.Email; set => base.Email = value; }
public string UplandUsername { get; set; }
public DateTime Nascimento { get; set; }
public decimal Saldo { get; set; }velEnum UplandLevel { get; set; }
public string FotoPerfil { get; set; }
public Company Company { get; set; } // RELATION HERE
}
`
THAT IS MY COMPANY CLASS:
`
public class Company : BaseEntity
{
public string Name { get; set; }
public string Country { get; set; }
public string Department { get; set; }
public string Usuario_Id { get; set; } // REFERENTIAL USER ID
public ApplicationUser User { get; set; } // RELATION HERE
}
`
THAT IS MY DBCONTEXT OF IDENTITY:
`
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
{
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
}
`
THAT IS MY DBCONTEXT OF THE REST OF ENTITIES, INCLUDING COMPANY:
`
public class MagnatumDbContext : DbContext
{
public MagnatumDbContext(DbContextOptions<MagnatumDbContext> options) : base(options) { }
public DbSet<Company> Companies { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var property in modelBuilder.Model.GetEntityTypes()
.SelectMany(e => e.GetProperties()
.Where(p => p.ClrType == typeof(string))))
property.SetColumnType("varchar(100)");
modelBuilder.ApplyConfigurationsFromAssembly(typeof(MagnatumDbContext).Assembly);
base.OnModelCreating(modelBuilder);
}
}
`
I would like to know how to configure this one to one relationship and where to configure it (applicationDBContext or MagnatumDbContext).

Related

EF Core Many-to-Many Relation Table Naming [duplicate]

This question already has answers here:
Change name of generated Join table ( Many to Many ) - EF Core 5
(2 answers)
Closed 1 year ago.
Does EF Core provide a way of naming the many-to-many relations mapping to database tables ?
In a code-first pattern, I have the following 2 Entities:
[Table("Prefix.Users")]
public class User
{
public int ID { get; set; }
public IEnumerable<Role> Roles { get; set; }
}
[Table("Prefix.Roles")]
public class Role
{
public int ID { get; set; }
public IEnumerable<User> Users { get; set; }
}
I've skipped the detailed Entity structure here. The ID properties in User & Role are keys (Database generated Identity)
User and Role entities share a many-to-many relationship.
EF Core generates a third table in Database with Table name UsersRoles
Is there a way I can add a prefix to the 3rd table name so it becomes Prefix.UsersRoles without manually adding a third Entity UserRoles that maps User and Role and giving it the desired name with Prefix
Use fluent API instead of using data annotations
Your model classes should be like this.
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
public class UserRole
{
public int UserId { get; set; }
public int RoleId { get; set; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
}
Your fluent api configuration classes like be this
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.ToTable("User");
builder.HasKey(x => x.Id);
}
}
public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
public void Configure(EntityTypeBuilder<Role> builder)
{
builder.ToTable("Role");
builder.HasKey(x => x.Id);
}
}
public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
{
public void Configure(EntityTypeBuilder<UserRole> builder)
{
builder.ToTable("UserRole");
builder.HasKey(x => new { x.UserId, x.RoleId });
builder
.HasOne<Role>(s => s.Role)
.WithMany(r => r.UserRoles)
.HasForeignKey(s => s.RoleId).OnDelete(DeleteBehavior.Restrict);
builder
.HasOne<User>(s => s.User)
.WithMany(r => r.UserRoles)
.HasForeignKey(s => s.UserId).OnDelete(DeleteBehavior.Restrict);
}
}
Your DbContext class should be like this
public class MyDbContext : DbContext
{
public EEGDbContext()
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(#"Server=xxxx;Database=DB;User Id=sa;Password=xxxxx;");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new UserConfiguration());
modelBuilder.ApplyConfiguration(new RoleConfiguration());
modelBuilder.ApplyConfiguration(new UserRoleConfiguration());
base.OnModelCreating(modelBuilder);
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
}

How to configure one-to-one relations to the same table in Entity Framework Core

I have a model as follows:
public class Category : BaseEntity
{
public string Name { get; set; }
public virtual Category Parent { get; set; }
public string Description { get; set; }
}
Parent property is related to the same table. How can i configure it?
I'm imagining something like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Category>()
.HasOne(a => a.Parent)
.OnDelete(false);
}
I'm newbie with Entity framework core, please help me !!!
Resoled by:
public class Category : BaseEntity
{
public string Name { get; set; }
public int? ParentId{ get; set; } /*added*/
[ForeignKey("ParentId")] /*added*/
public virtual Category Parent { get; set; }
public string Description { get; set; }
}

EF Core TPH Discriminator ignores base entities

I have two DbContext. A BaseDbContext and one that inherits from the BaseDbContextcalled FemaleDbContext.
public class BaseDbContext : DbContext
{
public BaseDbContext(DbContextOptions options) : base(options) { }
public virtual DbSet<Person> Person { get; set; }
public virtual DbSet<House> House { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>().ToTable("Person", "dbo");
modelBuilder.Entity<House>().ToTable("House", "dbo");
modelBuilder.Entity<Person>().HasOne(e => e.House).WithMany(e => e.Persons);
modelBuilder.Entity<House>().HasMany(e => e.Persons).WithOne(e => e.House);
}
}
The goal is to extend the Person entity with another property. I do not want to use shadow properties because its too dynamic. So I am trying to make it work using TPH. Here is my other context:
public class FemaleDbContext : BaseDbContext
{
public DbSet<Female> Female { get; set; }
public FemaleDbContext(DbContextOptions<FemaleDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Female>().HasBaseType<Person>();
base.OnModelCreating(modelBuilder);
}
}
As you can see, my sub-context should use the Female entity instead of the Person. The problem is that when I run this.Context.Female.ToList() on my SubDbContext, only entities with the value Female inside the Discriminator field inside my database are returned. Entities with the value Person in that table are returned. But I want to get every entity.
Also, here are my entities:
public class Person
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Middlename { get; set; }
public string Lastname { get; set; }
}
public class Female : Person
{
public bool? IsPregnant { get; set; }
}
How can I configure my DbContext that this.Context.Female.ToList() returns both Females and Persons. Note that this.Context.Person.ToList() already returns everything, not only Persons

How to map many-to-many with Code First to same class?

I use Code First with Entity Framework 5.
I have User class, where one user can be friends with many people.
public class User
{
[Key]
public Guid UserID { get; set; }
public virtual ICollection<User> Friends { get; set; }
}
This however maps 0..1-to-many. How should I map many-to-many relationship with the same class in Code First?
Add configuration class:
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
HasMany(u => u.Friends).WithMany();
}
}
then, this needs to be added to context class
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new UserConfiguration());
base.OnModelCreating(modelBuilder);
}
}
public class Organization : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public virtual Organization Parent { get; set; }
public virtual ICollection<Organization> Children { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class OrganizationConfiguration : EntityMapperBase<Organization>
{
public OrganizationConfiguration()
{
HasKey(f => f.Id);
Property(f => f.Name).HasMaxLength(20).IsRequired();
HasMany(f => f.Children).WithOptional(f => f.Parent).Map(m => m.MapKey("ParentId")).WillCascadeOnDelete(false);
HasMany(f => f.Users).WithRequired(f => f.Organization).Map(m => m.MapKey("OrganizationId"));
}
}
may it help you
You should have tow navigation properties
public class User
{
[Key]
public Guid UserID { get; set; }
public virtual ICollection<User> FriendsOfMine { get; set; }
public virtual ICollection<User> FriendsWithMe { get; set; }
}

Entity Framework 4.1 : The navigation property 'BusinessUser' declared on type 'Login' has been configured with conflicting multiplicities

I am having two entities
BusinessUser { Id(PK), Name,...}
Login { BusinessUserID(PK, FK), Email, Password, etc...}
Relationship between BusinessUser and Login is one-to-zero/one.
I am having following configurations
In BusinessUser EF configuration class
this.HasOptional(bu => bu.LoginInfo)
.WithOptionalPrincipal(l => l.BusinessUser);
In Login EF configuration class
this.HasRequired(l => l.BusinessUser)
.WithOptional(bu => bu.LoginInfo);
I am getting following exception
The navigation property 'BusinessUser' declared on type 'Login' has been configured
with conflicting multiplicities.
Where I am wrong with my one-to-one/zero configuration in EF 4.1 code first.
Update 1 : Following are my class structure
public class BusinessUser {
public virtual int ID { get; set; }
public virtual int BusinessID { get; set; }
public virtual Business Business { get; set; }
public Login LoginInfo { get; set; }
}
public class Login {
public virtual int BusinessUserID { get; set; }
public virtual string Email { get; set; }
public virtual string Password { get; set; }
public BUsinessUser BusinessUserInfo { get; set; }
}
Also I am looking for bi-directional.
Your BusinessUser must have relation configured as:
this.HasOptional(bu => bu.LoginInfo)
.WithRequired(l => l.BusinessUser);
Both configuration must be same (actually only one is needed) and the first configuration is incorrect because it is trying to define 0..1 - 0..1 relation.
How have you structured your classes ? Here's a sample with a relationship one-to-one/zero defined.
The result is :
BusinessUser { Id(PK), Name,...}
Login { BusinessUserID(PK, FK), Email, Password, etc...}
public class BusinessUser
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public virtual LoginInfo LoginInfo { get; set; }
}
public class LoginInfo
{
public int BusinessUserId { get; set; }
public virtual BusinessUser BusinessUser { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Here is the DbContext and the Initializer
public class MyContext : DbContext
{
public DbSet<BusinessUser> BusinessUsers { get; set; }
public DbSet<LoginInfo> LoginInfos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//We define the key for the LoginInfo table
modelBuilder.Entity<LoginInfo>().HasKey(x => x.BusinessUserId);
modelBuilder.Entity<LoginInfo>().HasRequired(bu => bu.BusinessUser);
}
}
public class MyInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(MyContext context)
{
var businessUser = new BusinessUser();
businessUser.Email = "mymail#email.com";
businessUser.Name = "My Name";
businessUser.LoginInfo = new LoginInfo(){Username = "myusername", Password ="mypassword"};
context.BusinessUsers.Add(businessUser);
context.SaveChanges();
}
}