Linq使用GroupBy时,Include无效

时间:2012-05-13 13:56:40

标签: linq-to-entities ef-code-first entity-framework-4.3

包括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);

如何让Include工作?

3 个答案:

答案 0 :(得分:42)

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);

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

答案 1 :(得分:26)

在这种特殊情况下,当你的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

答案 2 :(得分:0)

.Select() 之后的 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
                        })
                  }
                );