I've implemented Many-To-Many relationship and wonder if this is the optimal way for it. Since I do not have extensive EF Core experience I would love if someone with more experience could check it out.
Scenario:
- Many users
- Many organizations
- User can belong to multiple organizations
- Organization can hold multiple users
// Organization.cs
public class Organization
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual IEnumerable<OrganizationUser> OrganizationUsers { get; set; }
}
// OrganizationUser.cs
public class OrganizationUser
{
public Guid OrganizationId { get; set; }
public virtual Organization Organization { get; set; }
public Guid UserId { get; set; }
public virtual User User { get; set; }
public Role Role { get; set; }
}
public enum Role
{
Owner,
Admin,
User
}
// User.cs
public class User
{
public Guid Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public virtual IEnumerable<OrganizationUser> OrganizationUsers { get; set; }
[NotMapped]
public virtual IEnumerable<UserOrganizationOutputDto> Organizations
{
get
{
return OrganizationUsers.Select(x => new UserOrganizationOutputDto
{
Id = x.OrganizationId.ToString(),
Name = x.Organization.Name,
Role = x.Role
});
}
}
}
// Database Context code that is related
modelBuilder.Entity<Organization>()
.HasMany<OrganizationUser>()
.WithOne(x => x.Organization);
modelBuilder.Entity<User>()
.HasMany<OrganizationUser>()
.WithOne(x => x.User);
modelBuilder.Entity<OrganizationUser>()
.HasKey(x => new {x.OrganizationId, x.UserId});
modelBuilder.Entity<OrganizationUser>()
.HasOne(x => x.User)
.WithMany(x => x.OrganizationUsers)
.HasForeignKey(x => x.UserId);
modelBuilder.Entity<OrganizationUser>()
.HasOne(x => x.Organization)
.WithMany(x => x.OrganizationUsers)
.HasForeignKey(x => x.OrganizationId);
```
1 Answer 1
Couple of pointers. You are mixing data notation and fluent mapping.
replace NotMapped
attribute with .Ignore
fluent mapping.
Also I think its cleaner to move each entity into its own mapping config class using IEntityTypeConfiguration<T>
Dont mix DTO and entities like that. Best practice is to project your entities to DTOs.
-
\$\begingroup\$ Good point about
.Ignore
, will do that \$\endgroup\$sed– sed2020年06月18日 15:30:30 +00:00Commented Jun 18, 2020 at 15:30 -
\$\begingroup\$ You know, the reason I mix this DTO is that I need to get list of users and their respective role so this was the cleanest way I could imagine doing that. \$\endgroup\$sed– sed2020年06月18日 15:44:11 +00:00Commented Jun 18, 2020 at 15:44
-
\$\begingroup\$ I would project to a UserDto with a UserOrganizationOutputDto \$\endgroup\$Anders– Anders2020年06月18日 15:45:11 +00:00Commented Jun 18, 2020 at 15:45
-
\$\begingroup\$ x.Organization.Name forces you to use include otherwise you will get null reference error. with projection its not needed. Alot cleaner. Best practice too \$\endgroup\$Anders– Anders2020年06月18日 15:45:51 +00:00Commented Jun 18, 2020 at 15:45
Explore related questions
See similar questions with these tags.