《ASP.NET编程》18- linq查询表达式

1.序列
序列是LINQ的基础。在看到一个查询表达式的时候,应该要想到它所涉及的序列:一开始总是存在至少一个序列,且通常在中间过程会转换为其他序列,也可能和更多的序列连接在一 起。
来看一个简单的例子,我们在人员列表上执行一个查询表达式。附加了一个过滤器,来保证只有成年人出现在结果序列中:
var adultName = from person in people
where person.Age > 18
select person.Name;
下图以图表形式把这个查询表达式分解成了独立步骤。
每一个箭头代表一个序列——描述在左边,示例数据在右边。每个框都代表查询表达式的一个步骤。
2.延迟处理和流处理
上图中的查询表达式被创建的时候,不会处理任何数据,也不会访问原始的人员列表。而是在内存中生成了这个查询的表现形式。判断是否为成人的谓词,以及人到人名的转换,都是通过委托实例来表示的。只有在访问结果IEnumerable<string>的第一个元 素的时候,才会处理数据。

LINQ的这个特点称为延迟执行。在终结果的第一个元素被访问的时候,Select转换才会为它的第一个元素调用Where转换。而Where转换会访问列表中的第一个元素,检查这个谓词是否匹配(在这个例子中,是匹配的),并把这个元素返回给Select。后,依次提取出名称作为 结果返回。
3.LINQ查询语法
using System.Linq;
using static System.Console;

class Program
{
static void Main(string[] args)
{
string[] names = { "Alonso", "Zheng", "Smith", "Jones", "Smythe", "Small", "Ruiz", "Hsieh", "Jorgenson", "Ilyich", "Singh", "Samba", "Fatimah" };

    var queryResults =
        from n in names
        where n.StartsWith("S")
        select n;

    WriteLine("Names beginning with S:");

    foreach (var item in queryResults)
    {
        WriteLine(item);
    }

    Write("Program finished, press Enter/Return to continue:");
    ReadLine();
}

}
3.1 var关键字
LINQ查询首先声明一个变量,已包含查询的结果,这通常用var关键字声明来完成:
var queryResult = ... // 查询结果将是实现了IEnumerable<T>接口的类型

3.2 指定数据源:from语句
LINQ查询的下一部分是from语句,它指定了要查询的数据:
from n in names
变量n只是数据源names中的某一元素的代表,类似foreach语句后的变量名,源数据不能是单个值或对象。
3.3 指定条件:where子句
在LINQ查询的下一部分,可以使用where子句指定查询的条件:
where n.StartsWith("S")
3.4 选择元素:select子句
最后,select子句指定结果集中包含哪些元素:
select n;
3.5 完成:使用foreach语句循环
用foreach语句迭代结果:
foreach (var item in queryResults)
{
WriteLine(item);
}
3.6 延迟执行的查询
在访问查询结果(foreach)之前,并没有提取LINQ数据,这称为查询的延迟执行或迟缓执行。生成结果序列(即列表)的查询都要延迟执行。
4.LINQ方法语句
使用Lambda表达式与LINQ方法语句进行查询:
class Program
{
static void Main(string[] args)
{
string[] names = { "Alonso", "Zheng", "Smith", "Jones", "Smythe", "Small", "Rodriguez", "Hsieh", "Jorgenson", "Ilyich", "Singh", "Samba", "Fatimah" };

    var queryResults = names.Where(n => n.StartsWith("S")); // Where()方法的调用

    WriteLine("Names beginning with S:");
    foreach (var item in queryResults)
    {
        WriteLine(item);
    }

    Write("Program finished, press Enter/Return to continue:");
    ReadLine();

}

}
5.orderby子句
orderby子句如下所示:
// orderby n
class Program
{
static void Main(string[] args)
{
string[] names = { "Alonso", "Zheng", "Smith", "Jones", "Smythe", "Small", "Ruiz", "Hsieh", "Jorgenson", "Ilyich", "Singh", "Samba", "Fatimah" };

    var queryResults =
        from n in names
        where n.StartsWith("S")
        orderby n
        select n;

    WriteLine("Names beginning with S:");

    foreach (var item in queryResults)
    {
        WriteLine(item);
    }

    Write("Program finished, press Enter/Return to continue:");
    ReadLine();
}

}
通过LINQ方法语句查询:
var queryResults = names.Where(n => n.StartsWith("S")).Orderby(n => n);
多级排序:
orderby c.Region, c.Country descending, c.City // descending反转该字段排序(即逆序)
6.单值选择查询
LINQ提供了Distinct()方法查找获得唯一的不重复项(去除重复项)。
var queryResults = customers.Select(c => c.Region).Distinct();
class Customer
{
public string ID { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Region { get; set; }
public decimal Sales { get; set; }

public override string ToString()
{
    return "ID: " + ID + " City: " + City + " Country: " + Country + " Region: " + Region + " Sales: " + Sales;
}

}
class Program
{
static void Main(string[] args)
{
List<Customer> customers = new List<Customer> {
new Customer { ID="A", City="New York", Country="USA", Region="North America", Sales=9999},
new Customer { ID="B", City="Mumbai", Country="India", Region="Asia", Sales=8888},
new Customer { ID="C", City="Karachi", Country="Pakistan", Region="Asia", Sales=7777},
new Customer { ID="D", City="Delhi", Country="India", Region="Asia", Sales=6666},
new Customer { ID="E", City="São Paulo", Country="Brazil", Region="South America", Sales=5555 },
new Customer { ID="F", City="Moscow", Country="Russia", Region="Europe", Sales=4444 },
new Customer { ID="G", City="Seoul", Country="Korea", Region="Asia", Sales=3333 },
new Customer { ID="H", City="Istanbul", Country="Turkey", Region="Asia", Sales=2222 },
new Customer { ID="I", City="Shanghai", Country="China", Region="Asia", Sales=1111 },
new Customer { ID="J", City="Lagos", Country="Nigeria", Region="Africa", Sales=1000 },
new Customer { ID="K", City="Mexico City", Country="Mexico", Region="North America", Sales=2000 },
new Customer { ID="L", City="Jakarta", Country="Indonesia", Region="Asia", Sales=3000 },
new Customer { ID="M", City="Tokyo", Country="Japan", Region="Asia", Sales=4000 },
new Customer { ID="N", City="Los Angeles", Country="USA", Region="North America", Sales=5000 },
new Customer { ID="O", City="Cairo", Country="Egypt", Region="Africa", Sales=6000 },
new Customer { ID="P", City="Tehran", Country="Iran", Region="Asia", Sales=7000 },
new Customer { ID="Q", City="London", Country="UK", Region="Europe", Sales=8000 },
new Customer { ID="R", City="Beijing", Country="China", Region="Asia", Sales=9000 },
new Customer { ID="S", City="Bogotá", Country="Colombia", Region="South America", Sales=1001 },
new Customer { ID="T", City="Lima", Country="Peru", Region="South America", Sales=2002 }
};

    //method syntax
    var queryResults = customers.Select(c => c.Region).Distinct();
    //query syntax: var queryResults = (from c in customers select c.Region).Distinct();

    foreach (var item in queryResults)
    {
        WriteLine(item);
    }
    Write("Program finished, press Enter/Return to continue:");
    ReadLine();
}

}

7.使用聚合运算符
数字结果的聚合运算符:
运算符 说明
Count() 结果的个数
Min() 结果中的最小值
Max() 结果中的最大值
Average() 数字结果的品均值
Sum() 所有数字结果的总和
WriteLine(queryResults.Count());
8.组合查询
组合查询中的数据通过键(key)字段来组合,每个组的所以成员都共享这个字段,下例中的键字段为Region:
group c by c.Region
要和计算每个组的总和,应生成一个新的结果集cg:
group c by c.Region into cg
var queryResults =
from c in customers
group c by c.Region into cg
select new { TotalSales = cg.Sum(c => c.Sales), Region = cg.Key }
;
var orderedResults =
from cg in queryResults
orderby cg.TotalSales descending
select cg
;

WriteLine("Total\t: By\nSales\t: Region\n-----\t ------");
foreach (var item in orderedResults)
{
WriteLine($"{item.TotalSales}\t: {item.Region}");
}

9.Join查询
使用join,即可用一个查询搜索两个列表中的相关数据,用键字段把结果连接起来
9.1 内部联接
class Customer
{
public string ID { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Region { get; set; }
public decimal Sales { get; set; }
}
class Order
{
public string ID { get; set; }
public decimal Amount { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Order> orders = new List<Order> {
new Order { ID="P", Amount=100 },
new Order { ID="Q", Amount=200 },
new Order { ID="R", Amount=300 },
new Order { ID="S", Amount=400 },
new Order { ID="T", Amount=500 },
new Order { ID="U", Amount=600 },
new Order { ID="V", Amount=700 },
new Order { ID="W", Amount=800 },
new Order { ID="X", Amount=900 },
new Order { ID="Y", Amount=1000 },
new Order { ID="Z", Amount=1100 }
};
List<Customer> customers = new List<Customer> {
new Customer { ID="A", City="New York", Country="USA", Region="North America", Sales=9999},
new Customer { ID="B", City="Mumbai", Country="India", Region="Asia", Sales=8888},
new Customer { ID="C", City="Karachi", Country="Pakistan", Region="Asia", Sales=7777},
new Customer { ID="D", City="Delhi", Country="India", Region="Asia", Sales=6666},
new Customer { ID="E", City="São Paulo", Country="Brazil", Region="South America", Sales=5555 },
new Customer { ID="F", City="Moscow", Country="Russia", Region="Europe", Sales=4444 },
new Customer { ID="G", City="Seoul", Country="Korea", Region="Asia", Sales=3333 },
new Customer { ID="H", City="Istanbul", Country="Turkey", Region="Asia", Sales=2222 },
new Customer { ID="I", City="Shanghai", Country="China", Region="Asia", Sales=1111 },
new Customer { ID="J", City="Lagos", Country="Nigeria", Region="Africa", Sales=1000 },
new Customer { ID="K", City="Mexico City", Country="Mexico", Region="North America", Sales=2000 },
new Customer { ID="L", City="Jakarta", Country="Indonesia", Region="Asia", Sales=3000 },
new Customer { ID="M", City="Tokyo", Country="Japan", Region="Asia", Sales=4000 },
new Customer { ID="N", City="Los Angeles", Country="USA", Region="North America", Sales=5000 },
new Customer { ID="O", City="Cairo", Country="Egypt", Region="Africa", Sales=6000 },
new Customer { ID="P", City="Tehran", Country="Iran", Region="Asia", Sales=7000 },
new Customer { ID="Q", City="London", Country="UK", Region="Europe", Sales=8000 },
new Customer { ID="R", City="Beijing", Country="China", Region="Asia", Sales=9000 },
new Customer { ID="S", City="Bogotá", Country="Colombia", Region="South America", Sales=1001 },
new Customer { ID="T", City="Lima", Country="Peru", Region="South America", Sales=2002 }
};

    var queryResults =
        from c in customers
        join o in orders on c.ID equals o.ID
        select new { c.ID, c.City, SalesBefore = c.Sales, NewOrder = o.Amount, SalesAfter = c.Sales + o.Amount };

    foreach (var item in queryResults)
    {
        WriteLine(item);
    }

    Write("Program finished, press Enter/Return to continue:");
    ReadLine();
}

}

9.2 分组联接
使用join...into...实现分组连接

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

class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}

/// <summary>
/// This example performs a grouped join.
/// </summary>
public static void GroupJoinExample()
{
Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

Pet barley = new Pet { Name = "Barley", Owner = terry };
Pet boots = new Pet { Name = "Boots", Owner = terry };
Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

// Create two lists.
List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

// Create a list where each element is an anonymous type
// that contains the person's first name and a collection of 
// pets that are owned by them.
var query = from person in people
            join pet in pets on person equals pet.Owner into gj // join...into...语句
            select new { OwnerName = person.FirstName, Pets = gj };

foreach (var v in query)
{
    // Output the owner's name.
    Console.WriteLine($"{v.OwnerName}:");
    // Output each of the owner's pet's names.
    foreach (Pet pet in v.Pets)
        Console.WriteLine($"  {pet.Name}");
}

}

9.3 左外部联接
左外部联接是这样定义的:返回第一个集合的每个元素,无论该元素在第二个集合中是否有任何相关元素。 可以使用 LINQ 通过对分组联接的结果调用 DefaultIfEmpty 方法来执行左外部联接。

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

class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}

public static void LeftOuterJoinExample()
{
Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };

Pet barley = new Pet { Name = "Barley", Owner = terry };
Pet boots = new Pet { Name = "Boots", Owner = terry };
Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
Pet bluemoon = new Pet { Name = "Blue Moon", Owner = terry };
Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

// Create two lists.
List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
List<Pet> pets = new List<Pet> { barley, boots, whiskers, bluemoon, daisy };

var query = from person in people
            join pet in pets on person equals pet.Owner into gj
            from subpet in gj.DefaultIfEmpty() // 调用 DefaultIfEmpty 方法
            select new { person.FirstName, PetName = subpet?.Name ?? String.Empty };

foreach (var v in query)
{
    Console.WriteLine($"{v.FirstName+":",-15}{v.PetName}");
}

}

10.LINQ to XML
10.1 LINQ to XML函数构造方式
引入命名空间System.Xml.Linq

class Program
{
static void Main(string[] args)
{
XDocument xdoc = new XDocument( // XML文档
new XElement("BookStore", // 元素列表
new XElement("Book",
new XElement("Name", "C#", new XAttribute("BookName", "C#")), // 元素特性
new XElement("Author", "Martin", new XAttribute("Name", "Martin")),
new XElement("Adress", "ShangHai"),
new XElement("Date", DateTime.Now.ToString("yyyy-MM-dd"))
),
new XElement("Book",
new XElement("Name", "WCF", new XAttribute("BookName", "WCF")),
new XElement("Author", "Mary", new XAttribute("Name", "Mary")),
new XElement("Adress", "BeiJing"),
new XElement("Date", DateTime.Now.ToString("yyyy-MM-dd"))
)
)
)
);

    WriteLine(xdoc);
    ReadLine();

}

}

10.2 将XML写入文件

class Program
{
public static void CreatXmlTree(string xmlPath)
{
XElement xElement = new XElement(
new XElement("BookStore",
new XElement("Book",
new XElement("Name", "C#", new XAttribute("BookName", "C#")),
new XElement("Author", "Martin", new XAttribute("Name", "Martin")),
new XElement("Adress", "ShangHai"),
new XElement("Date", DateTime.Now.ToString("yyyy-MM-dd"))
),
new XElement("Book",
new XElement("Name", "WCF", new XAttribute("BookName", "WCF")),
new XElement("Author", "Mary", new XAttribute("Name", "Mary")),
new XElement("Adress", "BeiJing"),
new XElement("Date", DateTime.Now.ToString("yyyy-MM-dd"))
)
)
);
XmlWriterSettings settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(false),
Indent = true
};
XmlWriter xw = XmlWriter.Create(xmlPath, settings);
xElement.Save(xw);
//写入文件
xw.Flush();
xw.Close();
}
static void Main(string[] args)
{
string path = @"D:\BookStore.xml";
CreatXmlTree(path);
}
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341