C#实体框架 - 内部包含

时间:2017-03-23 14:31:15

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

我有一个名为项目的对象,该对象包含在该项目上工作的小时列表(由工作对象组成的列表)。 工作对象有一个名为 WorkDate 的成员,这是您处理该项目的那一天。我想要做的是获得两个日期之间的小时项目列表。但是,当我尝试在实体框架中进行此查询时,我得到以下错误。有谁知道如何在实体框架中编写此查询。我希望通过单个查询来实现这一点,而不是加载所有项目并在我的控制器中对它们进行排序。

为了更好地理解我正在尝试做什么,SQL示例在哪里。

在SQL中,我会通过连接来完成此操作。我有两个表项目工作。我会加入 Work.project_ID 上的工作和项目等于 Project.ID 然后选择Work.WorkDate在两个日期之间的所有项目行。

ProjectController.cs

[HttpGet("[action]")]
public async Task<IActionResult> GetProjectsByDate()
{
    try
    {
            var min = new DateTime(2017, 3, 1); 
            var max = new DateTime(2017, 3, 15);
            var projects = await context.Projects
                .Include(p => p.Hours)
                .ThenInclude(w => w.Where(h => h.WorkDate < max && h.WorkDate > min))
                .AsNoTracking()
                .ToListAsync(); 
             return Json(projects);
    }
}

Project.cs

public class Project
{
    [Key]
    public int ID { get; set; }
    public int? TeamID { get; set; }
    public int? ManagerID { get; set; }
    public int? CreatedBy { get; set; }

    public string Name { get; set; }
    public string Details { get; set; }
    public double? Estimate { get; set; }
    public bool IsActive { get; set; }

    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public DateTime CreatedDate { get; set; }

    [ForeignKey("TeamID")]
    public virtual Team Team { get; set; }
    [ForeignKey("ManagerID")]
    public virtual User Manager { get; set; }
    [ForeignKey("CreatedBy")]
    public virtual User Creator { get; set; }

    public virtual ICollection<Work> Hours { get; set; }


    public Project()
    {
        Hours = new List<Work>();
    }
}

项目输出

Message = "The property expression 'w => {from Work h in w where (([h].WorkDate < __max_0) AndAlso ([h].WorkDate > __min_1)) select [h]}' is not valid. The expression should represent a property access: 't => t.MyProperty'. For more information on including related d...

3 个答案:

答案 0 :(得分:2)

我没有让我的VS跑步,但期待以下作品:

[HttpGet("[action]")]
public async Task<IActionResult> GetProjectsByDate()
{
    try
    {
        var min = new DateTime(2017, 3, 1); 
        var max = new DateTime(2017, 3, 15);
        var projects = await context.Projects
            .Include(p => p.Hours)
            .Where(p => p.Hours.Any() && p.Hours.Where(w => w.WorkDate < max && w.WorkDate > min).Count() == p.Hours.Count)
            .AsNoTracking()
            .ToListAsync(); 
         return Json(projects);
    }
}

此代码确保返回其中所有小时数都在最小值和最大值之间的所有项目。

PS:另外,请注意,强烈建议在任何地方使用UTC时间,并且只在您向用户实际显示数据时才使用区域设置时间。

答案 1 :(得分:0)

显示它的简单控制台应用。

public class Project
  {        
    public int ID { get; set; }         
    public string ManagerName { get; set; }

    public virtual ICollection<Work> Hours { get; set; }

    public Project(int id, string managerName, List<Work> work)
    {
      ID = id;
      ManagerName = managerName;
      Hours = work;
    }
  }

  public class Work
  {
    public int WorkId { get; set; }
    public string WorkName { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }

    public Work(int workId, string workName, DateTime start, DateTime end)
    {
      WorkId = workId;
      WorkName = workName;
      Start = start;
      End = end;
    }
  }

  class Program
  {
    static void Main(string[] args)
    {

      var dtToday = DateTime.Now.Date;

      var projectsAndWork = new List<Project>
      {
        new Project(1, "A", new List<Work>{ new Work(1, "Stuff", dtToday.AddDays(-5), dtToday.AddDays(-3)), new Work(2, "Things", dtToday.AddDays(-5), dtToday.AddDays(-3)) }),
        new Project(2, "B", new List<Work>{ new Work(3, "More Stuff", dtToday.AddDays(-3), dtToday), new Work(4, "More Things", dtToday.AddDays(-3), dtToday) })
      };

      var hunt = dtToday.AddDays(-2);

      var projectForMoreStuff = projectsAndWork.Where(x => x.Hours.Any(y => y.Start <= hunt && y.End >= hunt));

      Console.ReadLine();
    }
  }

请注意,这将返回项目的整个结构及其所有孩子,你可以做'。选择(x =&gt;新项目(x.ID,x.ManagerName,null))只是范围到父对象。否则它会给你父母和所有孩子。但这是一种遍历一两级的方法,得到你想要的东西,并按照符合该标准的方式返回结构。

答案 2 :(得分:0)

使用Z.EntityFramework.Plus库

  

http://entityframework-plus.net/

所以你需要的就是这样做:

using Z.EntityFramework.Plus;

[HttpGet("[action]")]
public async Task<IActionResult> GetProjectsByDate()
{
    try
    {
        var min = new DateTime(2017, 3, 1); 
        var max = new DateTime(2017, 3, 15);
        var projects = await context.Projects
            .IncludeFilter(p => p.Hours
                    .Where(w => w.WorkDate < max && w.WorkDate > min))
            .AsNoTracking()
            .ToListAsync(); 
         return Json(projects);
    }
}

现在你也可以在你的包含中如此订购。