C
C#10mo ago
Joellao

✅ Database Scaffolding going wrong.

Hello all, reading the title you can imagine what I want to ask today. Using efcore to add migrations and scaffold the tables. I have this relationship
public class UserEntity : IdentityUser<int> {
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Bio { get; set; } = string.Empty;
public IEnumerable<PostEntity> Posts { get; set; }
public IEnumerable<GroupEntity> CreatedGroups { get; set; }
public IEnumerable<GroupEntity> ParticipatingGroups { get; set; }
}

public class GroupEntity{
[Key]
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public int CreatorId { get; set; }
public UserEntity Creator { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsPrivate { get; set; }
public IEnumerable<UserEntity> Members { get; set; }
}

public class UserGroupEntity {
[Key]
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public int CreatorId { get; set; }
public UserEntity Creator { get; set; }
public int UserId { get; set; }
public UserEntity User { get; set; }
public int GroupId{ get; set; }
public GroupEntity Group { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder
.Entity<GroupEntity>()
.HasOne(p => p.Creator)
.WithMany(u => u.CreatedGroups)
.HasForeignKey(p => p.CreatorId);

modelBuilder
.Entity<GroupEntity>()
.HasMany(e => e.Members)
.WithMany(e => e.ParticipatingGroups)
.UsingEntity<UserGroupEntity>();
}
public class UserEntity : IdentityUser<int> {
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Bio { get; set; } = string.Empty;
public IEnumerable<PostEntity> Posts { get; set; }
public IEnumerable<GroupEntity> CreatedGroups { get; set; }
public IEnumerable<GroupEntity> ParticipatingGroups { get; set; }
}

public class GroupEntity{
[Key]
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public int CreatorId { get; set; }
public UserEntity Creator { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsPrivate { get; set; }
public IEnumerable<UserEntity> Members { get; set; }
}

public class UserGroupEntity {
[Key]
public int Id { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public int CreatorId { get; set; }
public UserEntity Creator { get; set; }
public int UserId { get; set; }
public UserEntity User { get; set; }
public int GroupId{ get; set; }
public GroupEntity Group { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder
.Entity<GroupEntity>()
.HasOne(p => p.Creator)
.WithMany(u => u.CreatedGroups)
.HasForeignKey(p => p.CreatorId);

modelBuilder
.Entity<GroupEntity>()
.HasMany(e => e.Members)
.WithMany(e => e.ParticipatingGroups)
.UsingEntity<UserGroupEntity>();
}
13 Replies
Joellao
JoellaoOP10mo ago
Now this add the migration just fine, and updates fine. The only thing is that UserGroupEntity table adds a MembersId column with FK constraint and it doesn't let me creating a Group without filling it, but I don't have that in my relation. Am I missing something or am I just being dumb and can't see why is creating the MemberId column? What I'm trying to achieve even tho it should be quite easy to understand is that a User can create multiple Groups. Each user can be part of multiple groups and each group can have multiple users, hence the ManyToMany relationship with the UserGroupEntity. I want to track who creates what, so that's why I have also a Creator in the entities. I want to see who creates the Group, but also who adds someone to the Group
Omnissiah
Omnissiah10mo ago
are you omitting some attributes like inverse properties (eg UserEntity.Posts) voluntarily or are they missing
Joellao
JoellaoOP10mo ago
You mean on the OnModelCreating? I haven't specified them. I'm relying on efcore to handle it and it works fine I mapped the Creator because of this
The exception 'Unable to determine the relationship represented by navigation 'GroupEntity.Creator' of type 'UserEntity'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.'
The exception 'Unable to determine the relationship represented by navigation 'GroupEntity.Creator' of type 'UserEntity'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.'
And created the one for the UserGroupEntity because otherwise it creates a table on it's own, with only 2 columns, the UserId and the GroupId, but I want in the table other info as well, such as the creaotr, when it was created etc. Just to have some insights when the user has been added and whatever
V0FBU1VM
V0FBU1VM10mo ago
The error message you’re seeing is due to Entity Framework being unable to determine the relationship between GroupEntity and UserEntity through the Creator property. This is because you have multiple relationships between UserEntity and GroupEntity (one for CreatedGroups and another for ParticipatingGroups), and Entity Framework is unable to infer which navigation property pairs with which. To resolve this, you can explicitly configure the relationships in the OnModelCreating method.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<GroupEntity>()
.HasOne(p => p.Creator)
.WithMany(u => u.CreatedGroups)
.HasForeignKey(p => p.CreatorId)
.OnDelete(DeleteBehavior.Restrict); // Add this if you want to restrict delete

modelBuilder.Entity<GroupEntity>()
.HasMany(e => e.Members)
.WithMany(e => e.ParticipatingGroups)
.UsingEntity<UserGroupEntity>(
j => j
.HasOne(pt => pt.User)
.WithMany(t => t.ParticipatingGroups)
.HasForeignKey(pt => pt.UserId),
j => j
.HasOne(pt => pt.Group)
.WithMany(p => p.Members)
.HasForeignKey(pt => pt.GroupId));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity<GroupEntity>()
.HasOne(p => p.Creator)
.WithMany(u => u.CreatedGroups)
.HasForeignKey(p => p.CreatorId)
.OnDelete(DeleteBehavior.Restrict); // Add this if you want to restrict delete

modelBuilder.Entity<GroupEntity>()
.HasMany(e => e.Members)
.WithMany(e => e.ParticipatingGroups)
.UsingEntity<UserGroupEntity>(
j => j
.HasOne(pt => pt.User)
.WithMany(t => t.ParticipatingGroups)
.HasForeignKey(pt => pt.UserId),
j => j
.HasOne(pt => pt.Group)
.WithMany(p => p.Members)
.HasForeignKey(pt => pt.GroupId));
}
@Joellao Try that and see if it works.
Joellao
JoellaoOP10mo ago
That answer comes from Chat GPT right? catshy I have an error with .WithMany(t => t.Participant) because the ParticipatingGroups expects to be a UserGroupEntity Cannot convert expression type 'System.Collections.Generic.IEnumerable<Asd.Models.Entities.GroupEntity>' to return type 'System.Collections.Generic.IEnumerable<Asd.Models.Entities.UserGroupEntity>?'
V0FBU1VM
V0FBU1VM10mo ago
In the entities you provided, I cannot see any property named Participant?
Joellao
JoellaoOP10mo ago
Yeah, but it's the same, didn't copy it correctly
V0FBU1VM
V0FBU1VM10mo ago
Is UserGroupEntity suppose to be the joining table?
Joellao
JoellaoOP10mo ago
Yes
V0FBU1VM
V0FBU1VM10mo ago
Creator in UserGroupEntity is meant to show the person that added the user?
Joellao
JoellaoOP10mo ago
Yessir
V0FBU1VM
V0FBU1VM10mo ago
@Joellao
modelBuilder.Entity<GroupEntity>()
.HasMany(e => e.Members)
.WithMany(e => e.ParticipatingGroups)
.UsingEntity<UserGroupEntity>(
j => j
.HasOne(pt => pt.User)
.WithMany(t => t.ParticipatingGroups)
.HasForeignKey(pt => pt.UserId),
j => j
.HasOne(pt => pt.Group)
.WithMany(p => p.Members)
.HasForeignKey(pt => pt.GroupId),
j => j
.HasOne(pt => pt.Creator)
.WithMany()
.HasForeignKey(pt => pt.CreatorId));
modelBuilder.Entity<GroupEntity>()
.HasMany(e => e.Members)
.WithMany(e => e.ParticipatingGroups)
.UsingEntity<UserGroupEntity>(
j => j
.HasOne(pt => pt.User)
.WithMany(t => t.ParticipatingGroups)
.HasForeignKey(pt => pt.UserId),
j => j
.HasOne(pt => pt.Group)
.WithMany(p => p.Members)
.HasForeignKey(pt => pt.GroupId),
j => j
.HasOne(pt => pt.Creator)
.WithMany()
.HasForeignKey(pt => pt.CreatorId));
See if that makes any difference. I'm unable to try out what works and not. I can only give suggestions. So bear with me please.
Joellao
JoellaoOP10mo ago
Sorry for the late reply. I appreciate your suggestions, since I have nothing on my hand on my own, I can't go after you because you make suggestions. I can't do the relationships because ParticipatingGroups is not of type UserGroupEntity That's valid also for Members Solved this by introducint the UserGroupEntity in the GroupEntity and UserEntity. Wanted to avoid that, but no clues
Want results from more Discord servers?
Add your server