【问题标题】:EF Core One To Many IncludeEF Core 一对多包括
【发布时间】:2018-11-08 01:25:09
【问题描述】:

我在我的数据库中使用 EF-CORE 开发 ASP.NET Core MVC 网站。

我有一个Doc 表和一个Signature 表:

  • 一个Doc可以有多个Signatures
  • 一个Signature 只能在Doc 上拥有。

这是我的 Code First 实体模型:

文档

public class Doc
{
    [Key]
    public int DocID { get; set; }

    [Required]
    public int DocTypeID { get; set; }
    [ForeignKey("DocTypeID")]
    public virtual DocType DocType { get; set; }

    [Required]
    public int Version { get; set; }

    [Required]
    public Byte[] Data { get; set; }

    [ForeignKey("DocID")]
    public List<Signature> Signatures { get; set; }
}

签名

public class Signature
{
    //FK ITPolicyVersion
    [Key]
    public int DocID { get; set; }
    [ForeignKey("DocID")]
    public virtual Doc Doc { get; set; }

    //FK EmployeeID
    [Key]
    public int EmployeeID { get; set; }
    [ForeignKey("EmployeeID")]
    public virtual Employee Employee { get; set; }

    [Required]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
    [Display(Name = "Signature Date")]
    public DateTime? SignatureDate { get; set; }

    public String Value { get; set; }
}

但是当我使用这个请求时:

_applicationDBContext.Doc
    .Include(d => d.DocType)
    .Include(d => d.Signatures)
    .OrderBy(d => d.DocType)
    .ToList();

d.Signatures 始终为空,我不知道为什么。

这是我在 SQL 中尝试做的事情:

SELECT * FROM Doc d
JOIN DocType dt ON dt.DocTypeID = d.DocTypeID
JOIN Signature s ON s.DocID = d.DocID
JOIN Employee e ON e.EmployeeID = s.EmployeeID

这在 SQL 中运行良好,但不适用于 LINQ

编辑

这项工作:

List<Doc> docs = _applicationDBContext.Doc
    .Include(d => d.Signatures)
    .ThenInclude(s => s.Employee)
    .Include(d => d.DocType)
    .ToList();

但不是这个:

List<Doc> docs = _applicationDBContext.Doc
    .Include(d => d.Signatures)
    .ThenInclude(s => s.Employee)
    .Include(d => d.DocType)
    .OrderBy(d => d.DocType)
    .ToList();

Signature 变空了

如何通过DocType订购此列表?

【问题讨论】:

    标签: c# linq asp.net-core-mvc entity-framework-core


    【解决方案1】:

    orderby 实际上有一个错误,但它没有抛出:DocType 是另一个表并且没有实现 IComparable 所以我只是像这样更改请求:

    List<Doc> docs = _applicationDBContext.Doc
                                    .Include(d => d.Signatures)
                                        .ThenInclude(s=>s.Employee)
                                    .Include(d => d.DocType)
                                    .OrderBy(d => d.DocType.Name)
                                    .ToList();
    

    而且效果很好。

    【讨论】:

      【解决方案2】:

      在您的 DbContext 的 OnModelCreating 中,您是否放置了 Doc 和 Signature 的关系?像这样:

      modelBuilder.Entity<Signature>().HasOne(m => m.Doc).WithMany(m => m.Signature).HasForeignKey(m => m.DocID);
      

      【讨论】:

      • 我已经添加了这个:builder.Entity&lt;Signature&gt;().HasOne(m =&gt; m.Doc).WithMany(m =&gt; m.Signatures).HasForeignKey(m =&gt; m.DocID); 但它似乎不是更好,请查看编辑,我最初的请求可能不是我需要的
      • @Alexis 这是否解决了您原来的d.Signaturesnull 的问题(尽管即使没有流畅的配置也不应该发生)?编辑将您的原始问题变成了一个完全不同的问题,因此您应该删除编辑并发布一个单独的问题。但在此之前,您应该解决当前问题。
      • @IvanStoev 我会提出另一个问题,谢谢。您的解决方案没有解决签名问题,它仍然为空。
      【解决方案3】:

      看看ef core page on relationships

      你应该可以简化成这样的。

      请记住,很多事情都是按约定工作的,因此命名很重要(例如,实体框架会自动选择使用 Id 作为实体键)

      如果您在“子”对象上有向后导航属性,则需要外键属性和 id 属性或使用 Fluent API。

      public class Doc
      {
          public int Id { get; set; }
      
          public DocType DocType { get; set; }
      
          [Required]
          public int Version { get; set; }
      
          [Required]
          public Byte[] Data { get; set; }
      
          public List<Signature> Signatures { get; set; }
      }
      
      public class Signature {
      
          public int Id { get; set; }
      
          //backwards navigation
          public int DocForeignKey {get;set;}
          [ForeignKey("DocForeignKey")]
          public Doc Doc { get; set; }
      
          public Employee Employee { get; set; }
      
          [Required]
          [DataType(DataType.Date)]
          [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
          [Display(Name = "Signature Date")]
          public DateTime? SignatureDate { get; set; }
      
          public String Value { get; set; }
      }
      

      【讨论】:

      • 我知道 EF 的自动 ID,但我认为使用“tableNameID”之​​类的东西更清楚,添加 [KEY] 属性并不那么痛苦,我在 Doc for Signature 上向后导航。
      猜你喜欢
      • 1970-01-01
      • 2018-02-02
      • 2018-05-06
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多