首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EF用户实例中的多对多关系为空。

问EF用户实例中的多对多关系为空。
EN

Stack Overflow用户
提问于 2018-01-09 12:50:16
回答 1查看 2.1K关注 0票数 2

我正在使用.net核心2 mvc,我试图在Users和Steps之间建立多到多的关系。这种关系是没有关系的,但是当我查询记录时,我得到了user = null。

这是我的密码:

(applicationUser模型):

代码语言:javascript
复制
 public class ApplicationUser : IdentityUser
{
    public string Name { get; set; }
    public List<StepsUsers> StepUser { get; set; }
}

(步骤模型):

代码语言:javascript
复制
public class Steps
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    public List<StepsUsers> StepUser { get; set; }

}

StepsUsers模型:

代码语言:javascript
复制
public class StepsUsers : IAuditable
{
    public int StepId { get; set; }
    public Steps Step { get; set; }

    public string UserId { get; set; }
    public ApplicationUser User { get; set; }
}

在DbContext中,我这样做了:

代码语言:javascript
复制
protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);           
        builder.Entity<StepsUsers>()
        .HasKey(s => new { s.StepId, s.UserId });

        builder.Entity<StepsUsers>()
        .HasOne(su => su.Step)
        .WithMany(s => s.StepUser)
        .HasForeignKey(su => su.StepId);

        builder.Entity<StepsUsers>()
        .HasOne(su => su.User)
        .WithMany(s => s.StepUser)
        .HasForeignKey(su => su.UserId);
    }
public DbSet<MyApp.Models.StepsUsers> StepsUsers { get; set; }

现在,当我使用特定的StepsUsers查询StepId实例时,除了User字段是null之外,所有de字段都是正确的。

代码语言:javascript
复制
var stepUsers = await _context.StepsUsers.Where(s => s.StepId == id).ToListAsync();

我对另外两个表做了相同的代码,它工作得很好,我不知道为什么会这样,有什么建议吗?

EN

回答 1

Stack Overflow用户

发布于 2018-01-09 13:22:29

造成问题的原因是您忘记将您的许多关系声明为虚拟。另一个改进是将它们声明为虚拟ICollection而不是List。毕竟,ApplicationUser.StepUser4意味着什么?

如果根据“实体框架公约”,配置多到多的关系,则不需要提及连接表(StepsUsers)。实体框架将识别多到多,并将为您创建连接表。如果您坚持使用代码优先约定,您甚至不需要使用fluent API来配置多到多。

在您的设计中,每个ApplicationUser都有零个或多个Steps,每个Step都由零或多个ApplicationUsers完成。

代码语言:javascript
复制
class ApplicationUser
{
    public int Id {get; set;}

    // every ApplicationUser has zero or more Steps:
    public virtual ICollection<Step> Steps {get; set;}

    public string Name {get; set;}
    ...
}

class Step
{
    public int Id {get; set;}

    // every Step is performed by zero or more ApplicationUsers:
    public virtual ICollection<ApplicationUser> ApplicationUsers {get; set;}

    public string Name {get; set;}
    ...
}

public MyDbContext : DbContext
{
    public DbSet<ApplicationUser ApplictionUsers {get; set;}
    public DbSet<Step> Steps {get; set;}
}

这是所有实体框架需要知道的,以确认您配置了一个多到多的关系。实体框架将为您创建连接表和连接表的外键。你不需要声明连接表。

,但是如果没有连接表,我应该如何连接呢?

答案是:不做连接。使用集合代替.

如果你想要所有的ApplicationUsers .用他们所有的步骤..。通常,您将使用连接表进行内部连接,并通过一些组来获取应用程序用户。试过方法语法来连接三个表。吗?它们看起来很可怕,很难理解,容易出错,很难维护。

使用实体框架中的集合,查询就会简单得多:

代码语言:javascript
复制
var result = myDbContext.ApplicationUsers
    .Where(applicationUser => applicationUser.Name == ...)
    .Select(applicationUser => new
    {
         // select only the properties you plan to use:
         Name = applicationUser.Name,
         Steps = applicationUser.Steps
             .Where(step => step.Name == ...)
             .Select(step => new
             {
                 // again fetch only Step properties you  plan to use
                 Name = step.Name,
                 ...
             })
             .ToList(),
     });

实体框架将认识到连接表是必需的,并为您执行它们。

如果你想要的步骤..。他们的ApplicationUsers谁..。你会做一些类似的事情:

代码语言:javascript
复制
var result = myDbContext.Steps
   .Where(step => ...)
   .Select(step => new
    {
        Name = step.Name,
        ... // other properties
        ApplicationUsers = step.ApplicationUsers
            .Where(applicationUser => ...)
            .Select(applicationUser => new
            {
               ...
            })
            .ToList(),
    });

根据我的经验,每当我想到使用实体框架使用DbSets执行查询时,无论是在多对多、一对多或一对一的关系中,查询几乎总是可以使用集合而不是连接来创建。他们看起来更简单,他们更容易理解,因此更好地维护。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48168594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档