Linq 使用 GroupBy 时,Inclusion 不起作用

问题描述 投票:0回答:5

包括 matchparticipants 不起作用。当我调试时它总是说 Null。 但是当我将 GroupBy 放在注释中时,它工作正常。我正在使用实体框架 4.3.1 和代码优先。

实体:

public class Match
    {
        [ScaffoldColumn(false)]
        public int MatchId { get; set; }

        [Required(ErrorMessage = "Matchtype is a required field")]
        public int Scheme { get; set; }

        [Required]
        [DefaultValue(false)]
        public bool Finished { get; set; }

        public int Round { get; set; }


        // Relations
        [Required]
        public Category Category { get; set; }

        public Official Official { get; set; }

        public Slot Slot { get; set; }

        public ICollection<MatchParticipant> MatchParticipants { get; set; }
    }

 public class MatchParticipant
    {
        [ScaffoldColumn(false)]
        public int MatchParticipantId { get; set; }

        public int Points { get; set; }

        public int Goals { get; set; }

        [Required]
        public Match Match { get; set; }

        [Required]
        public Team Team { get; set; }
    }

public class Team
    {
        [ScaffoldColumn(false)]
        public int TeamId { get; set; }

        [Required(ErrorMessage="Name is a required field")]
        public string Name { get; set; }

        [Required(ErrorMessage="Number of players is a required field")]
        public int NumberOfPlayers { get; set; }

        [Required(ErrorMessage="Coach is a required field")]
        public string Coach { get; set; }

        [Required(ErrorMessage="Phone is a required field")]
        public string Phone { get; set; }

        public string CellPhone { get; set; }

        public string Fax { get; set; }

        [Required(ErrorMessage="Email is a required field")]
        public string Email { get; set; }

        [Required(ErrorMessage="Address is a required field")]
        public Address Address { get; set; }

        public Pool Pool { get; set; }

        [Required(ErrorMessage = "Category is a required field")]
        public Category Category { get; set; }

        public ICollection<MatchParticipant> matchParticipants { get; set; }
    }

        var matches =
        context.matches
       .Include("Official")
       .Include("Slot")
       .Include("MatchParticipants.Team")
       .Include("Category.Tournament")
       .Where(m => m.Category.Tournament.TournamentId == tournamentId)
       .GroupBy(m => m.Category);

如何使包含工作?

linq-to-entities ef-code-first entity-framework-4.3
5个回答
56
投票

Include
要求查询的形状不改变。这意味着您的查询必须返回
IQueryable<Match>
GroupBy
运算符可能被视为形状改变,因为它返回
IQueryable<IGrouping<TKey, TSource>>
。一旦查询的形状发生变化,所有 Include 语句都将被省略。因此,您不能将
Include
与投影、自定义连接和分组一起使用。

作为解决方法,您可以在 Linq-to-objects 中执行分组:

var matches = context.matches
                     .Include("Official")
                     .Include("Slot")
                     .Include("MatchParticipants.Team")
                     .Include("Category.Tournament")
                     .Where(m => m.Category.Tournament.TournamentId == tournamentId)
                     .ToList()
                     .GroupBy(m => m.Category);

编辑: 正如评论和其他答案中提到的,这是非常危险的解决方法,可能会导致性能问题。它将所有记录从数据库提取到应用程序,并在应用程序中进行聚合。它可以在相同的情况下工作,但它绝对不适用于通用解决方案。


37
投票

在这种特殊情况下,当您的 GroupBy 是最新的运算符时,此查询效果很好...但是恕我直言,上面的答案对于初学者来说是最糟糕的答案,因为当您的 GroupBy 未正确执行时,它会导致非常糟糕的优化查询在它之后,但后面跟着一些其他语句(Where、Select...)。 var ctx = new MyDataContext(); // Please use "using" var result = ctx.SomeTable //.Include(ah => ah.IncludedTable) // DO NOT PUT IT HERE .Where(t => t.IsWhateverTrue) .GroupBy(t => t.MyGroupingKey) .Select(gt => gt.OrderByDescending(d => d.SomeProperty) .FirstOrDefault(ah => ah.SomeAnotherFilter)) .Include(ah => ah.IncludedTable) // YES, PUT IT HERE .ToList(); // Execute query here


3
投票
之后的

GroupBy()

 中指定包含内容。这会将它们包含在结果中:
var result = ctx.SomeTable
                .Where(t => t.IsWhateverTrue)
                .GroupBy(t => t.MyGroupingKey)
                .Select(g => new
                  {
                    Date = g.Key.Value,
                    Reservations = g.Select(m => new
                        {
                          m,
                          m.IncludedTable // this selects/includes the related table
                        })
                  }
                );

您可以在 GroupBy() 之后的 .Select() 中实现 Include,如下所示:

0
投票
var query = ctx.Table .Where(x => "condition") .GroupBy(g => g.GroupingKeyId) .Select(x => new { GroupingKeyId = x.Key.GroupingKeyId, GroupingKey = x.Select(y => y.GroupingKey) .FirstOrDefault(y => y.Id == x.Key.GroupingKeyId) });

我找不到在 SQL 端使用实体框架进行分组,然后在 .net 站点上使用 Include() 的工作方法。另一种方法是编写您自己的 SQL 查询并进行自己的映射。
这实际上并不难:

-1
投票

在 Nuget 包管理器控制台中运行
    Install-Package dapper
  1. 进行实体映射

    定义要映射到的自定义对象(或使用现有对象)
  2. class MyClass { int userID; int numRows;}

    查询您的上下文对象:
  3. List<MyClass> results = _context.Database.GetDbConnection().Query<MyClass>("SELECT u.id as userID, count(1) as numRows FROM Users u inner join Table2 t2 on u.id= t2.userID group by u.id;").ToList();

        
© www.soinside.com 2019 - 2024. All rights reserved.