如何在以下数据集上执行Linq2Sql查询

时间:2010-05-11 12:44:23

标签: c# linq-to-sql

我有以下表格:

Person(Id, FirstName, LastName)
{
    (1, "John", "Doe"),
    (2, "Peter", "Svendson")
    (3, "Ola", "Hansen")
    (4, "Mary", "Pettersen")
}

Sports(Id, Name)
{
    (1, "Tennis")
    (2, "Soccer")
    (3, "Hockey")
}

SportsPerPerson(Id, PersonId, SportsId)
{
    (1, 1, 1)
    (2, 1, 3)
    (3, 2, 2)
    (4, 2, 3)
    (5, 3, 2)
    (6, 4, 1)
    (7, 4, 2)
    (8, 4, 3)
}

查看表格,我们可以得出以下事实:
约翰打网球 约翰扮演曲棍球 彼得踢足球 彼得打曲棍球 奥拉踢足球 玛丽打网球 玛丽踢足球 玛丽扮演曲棍球

现在我想创建一个Linq2Sql查询,它检索以下内容:
让所有玩曲棍球足球的人

执行查询应返回:Peter和Mary
任何人都知道如何在Linq2Sql中解决这个问题?

1 个答案:

答案 0 :(得分:1)

关于Linq的一个好处是,你不必将这一切都写成一个单一的查询,因为它无论如何都要实际执行,直到你无论如何都要枚举结果。您可以编写单个查询,但 。相反,您可以将其写为多个单独的查询,从而提高可读性并澄清您的意图。

var sportIds = Sports
    .Where(s => s.Name == "Hockey" || s.Name == "Soccer")
    .Select(s => s.Id);

var people = Person.Where(p => SportsPerPerson
    .Count(spp => (spp.PersonId == p.Id) 
    && sportIds.Contains(spp.SportId)) == 2);

首先,我们收集了我们感兴趣的运动项目。然后,我们在第一个列表中找到所有有两项运动的人。虽然它表示为多个查询,但当我们最终枚举结果时,Linq会将它全部压缩为一个操作。

编辑:这是一个完整的测试类,用于说明查询:

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace L2STest
{
    public class Sport
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public class SportPerPerson
    {
        public int Id { get; set; }
        public int PersonId { get; set; }
        public int SportId { get; set; }
    }

    [TestClass]
    public class SportsTest
    {
        private List<Person> persons;
        private List<Sport> sports;
        private List<SportPerPerson> sportsPerPerson;

         [TestInitialize]
         public void MyTestInitialize()
         {
             persons = new List<Person>
             {
                 new Person {Id = 1, FirstName = "John", LastName = "Doe"},
                 new Person {Id = 2, FirstName = "Peter", LastName = "Svendson"},
                 new Person {Id = 3, FirstName = "Ola", LastName = "Hansen"},
                 new Person {Id = 4, FirstName = "Marv", LastName = "Petterson"},
             };

             sports = new List<Sport>
             {
                 new Sport {Id = 1, Name = "Tennis"},
                 new Sport {Id = 2, Name = "Soccer"},
                 new Sport {Id = 3, Name = "Hockey"},
             };

             sportsPerPerson = new List<SportPerPerson>
             {
                 new SportPerPerson {Id = 1, PersonId = 1, SportId = 1}, 
                 new SportPerPerson {Id = 2, PersonId = 1, SportId = 3}, 
                 new SportPerPerson {Id = 3, PersonId = 2, SportId = 2}, 
                 new SportPerPerson {Id = 4, PersonId = 2, SportId = 3}, 
                 new SportPerPerson {Id = 5, PersonId = 3, SportId = 2}, 
                 new SportPerPerson {Id = 6, PersonId = 3, SportId = 1}, 
                 new SportPerPerson {Id = 7, PersonId = 4, SportId = 2}, 
                 new SportPerPerson {Id = 8, PersonId = 4, SportId = 3}, 
             };
         }

        [TestMethod]
        public void QueryTest()
        {
            var sportIds = sports
                .Where(s => s.Name == "Hockey" || s.Name == "Soccer")
                .Select(s => s.Id);

            var people = persons.Where(p => sportsPerPerson
                .Count(spp => (spp.PersonId == p.Id)
                && sportIds.Contains(spp.SportId)) == 2); 

            Assert.AreEqual(2, people.Count());
            Assert.AreEqual("Peter", people.First().FirstName);
            Assert.AreEqual("Marv", people.Last().FirstName);
        }
    }
}