gpt4 book ai didi

c# - 一个实体上的多个属性需要多对多关系 EF Core 2.2

转载 作者:行者123 更新时间:2023-12-02 03:15:04 25 4
gpt4 key购买 nike

我有一个用户实体和项目实体。

我需要能够将多个用户分配给我的项目实体上的 3 个不同的列表属性。我已经能够通过连接实体成功地为一个属性(多对多关系)完成此操作。我可以在 Users 表上指定 UserType 并仅使用一个属性,但我可能会遇到用户可能执行多个角色(类型)的情况,然后这将不起作用。

我以为我可以将 UserType 放在连接表(实体)上,但我不知道如何在 DBContext 中构建该实体。

这是我所拥有的与定义的一个属性一起使用的内容:

项目实体:

public class Project : IInt32Identity
{
public int Id { get; set; }
public string ProjectName { get; set; }
...
public bool ProjectActive { get; set; }
public List<ProjectFile> ProjectFiles { get; set; }
public List<ProjectUsers> ProjectUsers { get; set; }
public DateTime ProjectCreatedDate { get; set; }
public DateTime ProjectModifiedDate { get; set; }
}

用户实体:

public class User : IInt32Identity
{
public int Id { get; set; }
public string UserEmail { get; set; }
...
public List<ProjectUsers> ProjectUsers { get; set; }
public DateTime UserCreatedDate { get; set; }
public DateTime UserLastLoggedInDate { get; set; }
public DateTime UserModifiedDate { get; set; }
}

加入实体:

public class ProjectUsers
{
public int UserId { get; set; }
public User User { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}

还有我的 DBContext 中的 OnModelCreating()

    protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProjectUsers>()
.HasKey(bc => new { bc.UserId, bc.ProjectId });
modelBuilder.Entity<ProjectUsers>()
.HasOne(bc => bc.User)
.WithMany(b => b.ProjectUsers)
.HasForeignKey(bc => bc.UserId);
modelBuilder.Entity<ProjectUsers>()
.HasOne(bc => bc.Project)
.WithMany(c => c.ProjectUsers)
.HasForeignKey(bc => bc.ProjectId);
}

正如我上面所说,一切都很好,但这就是我想要的:

项目实体:

public class Project : IInt32Identity
{
public int Id { get; set; }
public string ProjectName { get; set; }
...
public bool ProjectActive { get; set; }
public List<ProjectFile> ProjectFiles { get; set; }
public List<ProjectUsers> ProjectClients { get; set; }
public List<ProjectUsers> ProjectBuilders { get; set; }
public List<ProjectUsers> ProjectDesigners { get; set; }
public DateTime ProjectCreatedDate { get; set; }
public DateTime ProjectModifiedDate { get; set; }
}

UserEntity 是相同的。

加入实体:

public class ProjectUsers
{
public int UserId { get; set; }
public User User { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
public string UserType { get; set; }
}

我迷失的是 OnModelBinding() 代码,我也不确定 EF 是否足够智能,可以根据该 UserType 正确填充列表> 元属性。

任何帮助或指导将不胜感激。

TIA

最佳答案

似乎可以将 ProjectUser 视为基类/实体,并为 ProjectClientProjectBuilder 创建不同的类/实体/类型和从 ProjectUser 继承的 ProjectDesigner。然后为每种类型以及与项目的一对多关系创建表。这通常称为按类型表 (TPT) 方法。

但是,TPT 尚未在 EF Core 中实现。

您仍然可以使用每个层次结构表 (TPH) 来实现此目的,但项目中的所有项目用户只有一个列表,其中 UserId, ProjectIdUserType 成为复杂的键。项目客户、建筑商和设计师将根据该项目用户列表计算属性。

实体

public class Project
{
public int Id { get; set; }
public string Name { get; set; }

public virtual ICollection<ProjectUser> ProjectUsers { get; set; }

public IEnumerable<ProjectUser> ProjectClients => this.ProjectUsers
.Where(x => x.UserType == "Client");
public IEnumerable<ProjectUser> ProjectBuilders => this.ProjectUsers
.Where(x => x.UserType == "Builder");
public IEnumerable<ProjectUser> ProjectDesigners => this.ProjectUsers
.Where(x => x.UserType == "Designer");
}

public class User
{
public int Id { get; set; }
public string Email { get; set; }

public virtual ICollection<ProjectUser> UserProjects { get; set; }
}

public class ProjectUser
{
public int UserId { get; set; }
public virtual User User { get; set; }

public int ProjectId { get; set; }
public virtual Project Project { get; set; }

public string UserType { get; set; }
}

配置

public class ProjectConfiguration : IEntityTypeConfiguration<Project>
{
public void Configure(EntityTypeBuilder<Project> builder)
{
builder.HasKey(x => x.Id);
builder.Property(x => x.Name).IsRequired();
builder.HasIndex(x => x.Name).IsUnique();

builder.Ignore(x => x.ProjectBuilders);
builder.Ignore(x => x.ProjectClients);
builder.Ignore(x => x.ProjectDesigners);

builder.ToTable("Project");
}
}

public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasKey(x => x.Id);
builder.Property(x => x.Email).IsRequired();
builder.HasIndex(x => x.Email).IsUnique();

builder.ToTable("User");
}
}

public class ProjectUserConfiguration : IEntityTypeConfiguration<ProjectUser>
{
public void Configure(EntityTypeBuilder<ProjectUser> builder)
{
builder.HasKey(x => new { x.ProjectId, x.UserId, x.UserType });
builder.Property(x => x.UserType).IsRequired();

builder.HasOne(x => x.Project)
.WithMany(x => x.ProjectUsers)
.HasForeignKey(x => x.ProjectId);

builder.HasOne(x => x.User)
.WithMany(x => x.UserProjects)
.HasForeignKey(x => x.UserId);
}
}

virtual 关键字用于延迟加载支持。如果您不进行延迟加载,则不必在那里使用virtual。此外,您还必须[NotMapped]这 3 个计算属性,这与在 Fluent API 中使用 .Ignore 相同。

数据库上下文

public class AppDbContext : DbContext
{
public DbSet<Project> Projects { get; set; }
public DbSet<User> Users { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.ApplyConfiguration(new ProjectConfiguration());
modelBuilder.ApplyConfiguration(new UserConfiguration());
modelBuilder.ApplyConfiguration(new ProjectUserConfiguration());
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);

optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer("Data Source=.\\SQLEXPRESS;Initial Catalog=DL.SO.ProjectUsersDemo;Integrated Security=True;MultipleActiveResultSets=False;");
}
}

这里没什么特别的。添加迁移并更新数据库后,您的数据库应该如下所示

enter image description here

用示例数据填充数据库后,虽然很难在此处显示,但您可以看到这 3 个列表填充了正确的数据:

enter image description here

关于c# - 一个实体上的多个属性需要多对多关系 EF Core 2.2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56369669/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com