实体框架 7 DbContext OnModelCreating 指定 ApplicationUser 字段的外键

本文关键字:字段 ApplicationUser 指定 框架 DbContext OnModelCreating 实体 | 更新日期: 2023-09-27 18:36:38

我正在尝试实现与此 EF7 流畅 API 文档中发生的事情非常相似的东西,但事实并非如此。

我有一个看起来像这样的模型:

public class BlogPost
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public string CreatedBy {get; set; }
    public ApplicationUser CreatedByUser { get; set; }
}

我的应用程序用户类中没有任何与博客文章相关的内容。因此,连接实际上并不需要双向进行。

有人可以告诉我,对于我的情况,我如何告诉实体框架,在使用包含时,我想要填充 CreatedByUser,基于 BlogPost 中的 CreatedBy 字段等于 AspNetUsers 表中的用户名字段?

以下是我希望能够在我的存储库中执行的操作:

using (var blogContext = new BlogContext())
{
  return blogContext .BlogPosts
    .Include(bp => bp.CreatedByUser)
}

这是我最好的尝试:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<BlogPost>()
        .HasOne(fp => fp.CreatedByUser)
        .WithMany()
        .HasForeignKey(fp => fp.CreatedBy)
        .IsRequired();
}

我觉得这里的诀窍不是向.WithMany(),因为在我的模型中,我的应用程序用户模型中没有 List 属性。

导致我问题的主要原因是,默认情况下,EF 尝试使用 Id 字段作为 AspNetUsers 表中的键。我想告诉它使用用户名作为密钥,而不是 guid。

实体框架 7 DbContext OnModelCreating 指定 ApplicationUser 字段的外键

我想

出了一个完美运行的解决方案。

以下是需要放入 DbContext 文件中才能使其正常工作的 Fluent API 代码:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    // Need to do this because if using as a foreign key it must match the length of the principal key
    builder.Entity<BlogPost>()
        .Property(fp => fp.CreatedBy)
        .HasMaxLength(256);
    // A BlogPost has one CreatedByUser (notice we must specify the PrincipalKey to be UserName from the AspNetUsers table otherwise EF would attempt to use the Id (Guid) field by default)
    builder.Entity<BlogPost>()
        .HasOne(bp => bp.CreatedByUser)
        .WithMany()
        .HasForeignKey(bp => bp.CreatedBy)
        .HasPrincipalKey(u => u.UserName)
        .IsRequired();
}

然后在我的存储库中,我可以简单地执行以下操作来确保绑定 CreatedByUser:

public IEnumerable<BlogPost> GetBlogPosts()
{
    return _context.BlogPosts
    .Include(bp => bp.CreatedByUser)
    .ToList();
}

这是我的模型的样子:

public class BlogPost
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    // Foreign Key
    public string CreatedBy { get; set; }
    // Navigation Property
    public ApplicationUser CreatedByUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

由于几乎所有对象都有一个 CreatedBy 字段,我需要在其中获取整个用户才能在我的视图中显示名字、姓氏、电子邮件等内容,我假设我会做很多事情。我可能很少需要通过用户检索我的任何实体的列表,但是如果我这样做,我会将列表 MyObjects 添加到 ApplicationUser 模型,然后在 .WithMany(b => b.MyObjects) params.

如果有人有任何反馈或其他意见,请告诉我。