【问题标题】:Returning many-to-many results with LINQ in C# asp.net在 C# asp.net 中使用 LINQ 返回多对多结果
【发布时间】:2017-07-02 03:16:05
【问题描述】:

我正在努力理解 LINQ 语法以及如何将它与数据库中的多对多关系一起使用。在我的示例项目中,我正在对汽车进行建模,并且您可以对汽车进行维护。所以我有 3 张桌子:

  1. 汽车(用户添加的汽车信息)
  2. 服务(仅供参考)
  3. CarServices(存储在汽车上完成的服务)

在网站上,我显示了来自所有 3 个表的信息,因此我创建了一个视图模型 CarsIndexViewModel 来保存汽车及其关联的 CarServices。

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

    [Required]
    [StringLength(40)]
    public string Name { get; set; }

    [Required]
    [Range(1900, 2018)]
    public int Year { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public string Color { get; set; }
    public int Mileage { get; set; }

    public virtual ICollection<CarService> CarServices { get; set; }
}

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

    public virtual ICollection<CarService> CarServices { get; set; }

}

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

    public int CarId { get; set; }

    [Required]
    [Display(Name = "Service")]
    public int ServiceId { get; set; }

    [Required]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    [Display(Name = "Date of Service")]
    public DateTime ServiceDate { get; set; }

    [Column(TypeName = "Money")]
    public decimal? Cost { get; set; }

    public bool HasReceipt { get; set; }

    [Required]
    [Display(Name = "Mileage At Time of Service")]
    public int Mileage { get; set; }

    public virtual Car Car { get; set; }
    public virtual Service Service { get; set; }
}

和视图模型:

public class CarsIndexViewModel
{
    public Car Car { get; set; }
    public IEnumerable<CarService> Services { get; set; }
}

通过在我的控制器中使用此代码,我已经能够返回所有服务及其信息:

var query = (
            from car in _context.Cars
            select new CarsIndexViewModel()
            {
                Car = car,
                Services = car.CarServices
            }).ToList();

return View(query);

我不知道如何只返回满足特定条件的 CarServices。例如,如果我只想显示最近日期的 CarServices 怎么办?

【问题讨论】:

    标签: c# asp.net-mvc linq


    【解决方案1】:

    如果您想显示最近的服务:

    var query = (from car in _context.Cars
                 select new CarsIndexViewModel()
                 {
                     Car = car,
                     Services = car.CarServices
                                   .OrderByDescending(cs => cs.ServiceDate)
                                   .Take(5) // only 5 most recent
                                   .ToList()
                 }).ToList();
    

    【讨论】:

      【解决方案2】:

      有很多方法可以做到这一点。了解您正在谈论的内容的几种可能性(显示最近日期的 CarServices)是:

      最近n最近的服务:

      var n = 4;
      var query = (
              from car in _context.Cars
              select new CarsIndexViewModel()
              {
                  Car = car,
                  AllServices = car.CarServices,
                  RecentServices = car.CarServices.OrderBy(x => ServiceDate).Take(n)
              }).ToList();
      

      给定日期之后的最近服务:

      var recentThreshold = new DateTime(2017,01,01);
      var query = (
              from car in _context.Cars
              select new CarsIndexViewModel()
              {
                  Car = car,
                  AllServices = car.CarServices,
                  RecentServices = car.CarServices.Where(x => ServiceDate > recentThreshhold)
              }).ToList();
      

      最近的服务都发生在提供任何服务的最后一天:

      var latestServiceDates = (
              from car in _context.Cars
              select new KeyValuePair<int, DateTime>()
              {
                  Key = car.id,
                  Value = car.CarServices.OrderByDescending(x => ServiceDate).First()
              }).ToList();
      var query = (
              from car in _context.Cars
              select new CarsIndexViewModel()
              {
                  Car = car,
                  AllServices = car.CarServices,
                  RecentServices = car.CarServices.Where(x => ServiceDate = latestServiceDates.First(y => y.Key == x.id))
              }).ToList();
      

      这完全取决于你想要做什么。

      【讨论】:

      • 感谢您的回复!我想要的与您的第二个示例类似,但我希望 recentThreshold 等于 CarServices 中的最近日期。例如,如果汽车最近一次是在 2 月 2 日在店里,并且完成了换油和轮胎更换,我只想从 CarServices 退回这两行。
      • 检查我更新的答案。我添加了一个选项,希望能得到你需要的东西。我假设您的 car 对象具有某种标识符?我正在使用这个假设为每辆车的最新服务日期建立一个查找表。我用id。如果它被命名为别的东西,你将不得不使用它。如果您对此有任何疑问,请告诉我。
      • Key 和 Value 是 KeyValuePair 的只读属性,因此您必须在构造函数中传入这些值。但是,看起来 LINQ 不允许您使用带参数的构造函数。我尝试先创建一个具有 id 和日期的对象,然后在内存中创建确实有效的 KeyValuePairs。但现在我得到一个例外,我认为是尝试结合 LINQ->Object 和 LINQ->EF。
      • 好的,抱歉。我写了它,不得不冲出去。我应该更彻底地查找 KeyValuePair 。但大体概念应该是一样的。那么您现在是否可以正常工作,还是仍然出现错误?
      • 我认为这个概念很好,但是在尝试运行第二个语句时我仍然卡在这个 NotSupportedException 上。我认为这是尝试将内存中的 LINQ-> 对象和 LINQ-> EF 结合起来。我正在考虑只是撤回所有内容并在事后使用 for 循环或其他东西进行过滤!
      猜你喜欢
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-18
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      相关资源
      最近更新 更多