C
C#5mo 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
Joellao5mo 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
WEIRD FLEX
WEIRD FLEX5mo ago
are you omitting some attributes like inverse properties (eg UserEntity.Posts) voluntarily or are they missing
Joellao
Joellao5mo 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
SwaggerLife
SwaggerLife5mo 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
Joellao5mo 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>?'
SwaggerLife
SwaggerLife5mo ago
In the entities you provided, I cannot see any property named Participant?
Joellao
Joellao5mo ago
Yeah, but it's the same, didn't copy it correctly
SwaggerLife
SwaggerLife5mo ago
Is UserGroupEntity suppose to be the joining table?
Joellao
Joellao5mo ago
Yes
SwaggerLife
SwaggerLife5mo ago
Creator in UserGroupEntity is meant to show the person that added the user?
Joellao
Joellao5mo ago
Yessir
SwaggerLife
SwaggerLife5mo 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
Joellao5mo 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
More Posts