我一直在搜索Select和SelectMany之间的区别,但我还没有找到合适的答案。我需要学习使用LINQ to SQL时的差异,但我所找到的都是标准数组示例。

有人能提供一个LINQ到SQL的例子吗?


当前回答

再举一个如何使用SelectMany + Select来累积子数组对象数据的例子。

假设我们有一些带着手机的用户:

class Phone { 
    public string BasePart = "555-xxx-xxx"; 
}

class User { 
    public string Name = "Xxxxx";
    public List<Phone> Phones; 
}

现在我们需要选择所有用户的所有手机的basepart:

var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();

其他回答

想想这个例子:

        var array = new string[2]
        {
            "I like what I like",
            "I like what you like"
        };
        //query1 returns two elements sth like this:
        //fisrt element would be array[5]  :[0] = "I" "like" "what" "I" "like"
        //second element would be array[5] :[1] = "I" "like" "what" "you" "like"
        IEnumerable<string[]> query1 = array.Select(s => s.Split(' ')).Distinct();

        //query2 return back flat result sth like this :
        // "I" "like" "what" "you"
        IEnumerable<string> query2 = array.SelectMany(s => s.Split(' ')).Distinct();

因此,正如你所看到的,像“I”或“like”这样的重复值已从query2中删除,因为“SelectMany”将在多个序列上平坦和投影。 但是query1返回字符串数组序列。由于query1中有两个不同的数组(第一个和第二个元素),因此不会删除任何东西。

我理解SelectMany工作起来像一个连接快捷方式。

所以你可以:

var orders = customers
             .Where(c => c.CustomerName == "Acme")
             .SelectMany(c => c.Orders);

SelectMany()方法用于抚平序列,其中序列的每个元素都是独立的。

我的类用户是这样的

class User
    {
        public string UserName { get; set; }
        public List<string> Roles { get; set; }
    }

主要:

var users = new List<User>
            {
                new User { UserName = "Reza" , Roles = new List<string>{"Superadmin" } },
                new User { UserName = "Amin" , Roles = new List<string>{"Guest","Reseption" } },
                new User { UserName = "Nima" , Roles = new List<string>{"Nurse","Guest" } },
            };

var query = users.SelectMany(user => user.Roles, (user, role) => new { user.UserName, role });

foreach (var obj in query)
{
    Console.WriteLine(obj);
}
//output

//{ UserName = Reza, role = Superadmin }
//{ UserName = Amin, role = Guest }
//{ UserName = Amin, role = Reseption }
//{ UserName = Nima, role = Nurse }
//{ UserName = Nima, role = Guest }

您可以对序列的任何项使用操作

int[][] numbers = {
                new[] {1, 2, 3},
                new[] {4},
                new[] {5, 6 , 6 , 2 , 7, 8},
                new[] {12, 14}
            };

IEnumerable<int> result = numbers
                .SelectMany(array => array.Distinct())
                .OrderBy(x => x);

//output

//{ 1, 2 , 2 , 3, 4, 5, 6, 7, 8, 12, 14 }
 List<List<int>> numbers = new List<List<int>> {
                new List<int> {1, 2, 3},
                new List<int> {12},
                new List<int> {5, 6, 5, 7},
                new List<int> {10, 10, 10, 12}
            };

 IEnumerable<int> result = numbers
                .SelectMany(list => list)
                .Distinct()
                .OrderBy(x=>x);

//output

// { 1, 2, 3, 5, 6, 7, 10, 12 }

Some SelectMany可能不需要。以下2个查询给出相同的结果。

Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)

Orders.Where(o=>o.Customer.Name=="Tom")

对于一对多关系,

如果从“1”开始,则需要SelectMany,它将平展many。 如果从“Many”开始,则不需要SelectMany。(仍然能够从“1”中过滤,这也比以下标准的连接查询更简单)


from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o

假设你有一组国家

var countries = new[] { "France", "Italy" };

如果你对国家执行Select,你将得到数组中的每个元素IEnumerable<T>

IEnumerable<string> selectQuery = countries.Select(country => country);

在上面的代码中,国家表示指向数组中每个国家的字符串。现在迭代selectQuery以获得国家:

foreach(var country in selectQuery)
    Console.WriteLine(country);

// output
//
// France
// Italy

如果你想打印每个国家的字符,你必须使用嵌套foreach

foreach (var country in selectQuery)
{
    foreach (var charOfCountry in country)
    {
        Console.Write(charOfCountry + ", ");
    }
}

// output

// F, r, a, n, c, e, I, t, a, l, y,

好的。现在尝试对国家执行SelectMany。这一次SelectMany获取每个国家作为字符串(和以前一样),因为字符串类型是一个字符的集合,SelectMany尝试将每个国家分为它的组成部分(字符),然后返回一个字符的集合IEnumerable<T>

IEnumerable<char> selectManyQuery = countries.SelectMany(country => country);

在上面的代码中,country表示一个字符串,该字符串引用数组中的每个国家,但返回值是每个国家的字符

实际上SelectMany喜欢在集合中获取两层,并将第二层平铺为IEnumerable<T>

现在遍历selectManyQuery以获得每个国家的字符:

foreach(var charOfCountry in selectManyQuery)
    Console.Write(charOfCountry + ", ");

// output

// F, r, a, n, c, e, I, t, a, l, y,