日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

LINQ之路11:LINQ Operators之過濾(Filtering)

 印度阿三17 2019-06-27

在本系列博客前面的篇章中,已經(jīng)對LINQ的作用、C# 3.0為LINQ提供的新特性,還有幾種典型的LINQ技術:LINQ to Objects、LINQ to SQL、Entity Framework進行了比較詳細的介紹,至此,我們應該了解了各種LINQ技術之間的聯(lián)系和區(qū)別。千里之行始于足下,這些基礎理論是理解和使用LINQ的關鍵。但是我們在前面的文章中對于LINQ查詢運算符(LINQ Operators)并沒有完整的介紹,這就是接下來這幾篇博客中所要做的工作。大家可以按順序依次對各個LINQ Operators進行學習,也可以把他們看成一個reference,作為參考查詢之用。

示例數(shù)據(jù)

在這幾篇討論LINQ Operators的文章中,所有的示例都會(如果需要)用到下面的names數(shù)組:

            string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };

所有查詢數(shù)據(jù)庫的示例都會假設我們創(chuàng)建了強類型的DataCotnext變量dataContext,如下:

        var dataContext = new LifePoemContext ("connection string...");
...
public class LifePoemContext : DataContext
{
public LifePoemContext (string cxString) : base (cxString) {}
public Table<Customer> Customers { get { return GetTable<Customer>(); } }
public Table<Purchase> Purchases { get { return GetTable<Purchase>(); } }
}

[Table] public class Customer
{
[Column(IsPrimaryKey=true)] public int ID;
[Column] public string Name;

[Association (OtherKey="CustomerID")]
public EntitySet<Purchase> Purchases = new EntitySet<Purchase>();
}

[Table] public class Purchase
{
[Column(IsPrimaryKey=true)] public int ID;
[Column] public int? CustomerID;
[Column] public string Description;
[Column] public decimal Price;

EntityRef<Customer> custRef;
[Association (Storage="custRef",ThisKey="CustomerID",IsForeignKey=true)]
public Customer Customer
{
get { return custRef.Entity; } set { custRef.Entity = value; }
}
}

上面的DataContext和實體類是LINQ to SQL工具(如通過Visual Studio新增一個”LINQ to SQL Classes” Item)生成的簡化版本。其中Customer和Purchase包含了一個簡單的1:多關系,下面是對應的SQL表定義:

        create table Customer
(
ID int not null primary key,
Name varchar(30) not null
)
create table Purchase
(
ID int not null primary key,
CustomerID int references Customer (ID),
Description varchar(30) not null,
Price decimal not null
)

Filtering Operators

IEnumerable<TSource> → IEnumerable<TSource>

返回輸入sequence中元素的一個子集

Operator

說明

SQL語義

Where

返回符合給定條件的elements子集

WHERE

Take

返回開始的N個元素,忽略剩下的元素

WHERE   ROW_NUMBER()...

或TOP n 子句

Skip

忽略開始的N歌元素,返回之后的元素

WHERE ROW_NUMBER()...

或NOT IN (SELECT TOP n...)

TakeWhile

返回輸入sequence中的元素,直到指定條件為false,然后忽略剩下的元素

Exception   thrown

SkipWhile

忽略輸入sequence中的元素,直到指定條件為false,然后返回剩下的元素

Exception thrown

Distinct

返回去除重復元素的sequence

SELECT   DISTINCT...

對每一個過濾方法而言,總是得到一個少于或等于初始元素個數(shù)的序列,而不可能返回更多的元素!并且這些元素不會經(jīng)過任何改變,而是與原始元素一致。

Where

參數(shù)

類型

Source sequence

IEnumerable<TSource>

Predicate/條件

TSource   => bool or (TSource,int) => boola

a帶索引的lambda表達式在LINQ to SQL和Entity Framework中不可用。

查詢表達式語法:where bool-expression

Enumerable.Where實現(xiàn)

Enumerable.Where的內(nèi)部實現(xiàn)大致如下(略去null引用的檢查):

        public static IEnumerable<TSource> Where<TSource>
(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (TSource element in source)
if (predicate(element))
yield return element;
}

介紹

Where返回輸入sequence中滿足指定條件的elements,比如:

            string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
IEnumerable<string> query = names.Where(name => name.EndsWith("y"));
// Result: { "Harry", "Mary", "Jay" }

對應的查詢表達式語法:

            IEnumerable<string> query = from n in names
where n.EndsWith("y")
select n;

在一個查詢中where子句可以出現(xiàn)多次并且可以和let子句搭配使用:

            string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
IEnumerable<string> query = from n in names
where n.Length > 3
let u = n.ToUpper()
where u.EndsWith("Y")
select u;
// Result: { "HARRY", "MARY" }

索引過濾

Where的條件支持第二個可選參數(shù),類型為int,它的值等于每個element在輸入sequence中的位置,這樣我們就可以在lambda表達式中使用這個index信息。比如,下面的例子忽略index為單數(shù)的elements:

            IEnumerable<string> query = names.Where((n, i) => i % 2 == 0);
// Result: { "Tom", "Harry", "Jay" }

如果你在LINQ to SQL或Entity Framework中使用索引參數(shù),將會拋出異常。

LINQ to SQL和EF中的SQL LIKE 比較

下面這些字符串方法會被翻譯成SQL的LIKE操作符:Contains、StartsWith、EndsWith。

比如:c.Name.Contains ("abc") 翻譯成customer.Name LIKE '?c%' (或者與之等價的參數(shù)版本)。

需要注意的是,在使用Contains時,我們只能用來與本地計算的表達式進行比較,如果要和另外一列進行比較,我們必須借助于SqlMethod.Like方法:

            IQueryable<Purchase> query = purchases
.Where(p => SqlMethods.Like(p.Description, "%" p.Customer.Name "%"))
.OrderBy(p => p.ID)
.Select(p => p);

LINQ to SQL和EF中的WHERE x IN (..., ..., ...)

對于LINQ to SQL和EF,我們可以在過濾條件中對一個本地集合應用Contains方法,比如:

            string[] chosenOnes = { "Tom", "Jay" };

IQueryable<Customer> query =
from c in dataContext.Customers
where chosenOnes.Contains(c.Name)
select c;

這會映射到SQL的IN操作符,即:WHERE customer.Name IN ("Tom", "Jay")。如果本地集合是一個entities數(shù)組或其他的非標量類型,LINQ to SQL和EF可能會生成EXISTS子句。

Take和Skips

參數(shù)

類型

Source sequence

IEnumerable<TSource>

獲取或忽略的elements個數(shù)

int

Take返回前面n個元素并丟棄剩下的元素;Skip丟棄前面n個元素并返回剩下的元素。這兩個方法通常一起使用以實現(xiàn)web頁面的數(shù)據(jù)分頁效果,讓用戶能在一個大型的結(jié)果集上進行導航,比如:

            // 假設用戶在一個圖書數(shù)據(jù)庫中查找包含"mercury"的所有圖書
// 如果查找結(jié)果包含100條記錄,下面的查詢會返回前面20條
IQueryable<Book> query = dataContext.Books
.Where (b => b.Title.Contains ("mercury"))
.OrderBy (b => b.Title)
.Take (20);

// 下面的查詢則返回第21到40行數(shù)據(jù)(第2頁)
IQueryable<Book> query = dataContext.Books
.Where (b => b.Title.Contains ("mercury"))
.OrderBy (b => b.Title)
.Skip (20).Take (20);

對于SQL Server 2005,LINQ to SQL和EF 會把Take和Skip翻譯成ROW_NUMBER函數(shù),而對于更早的SQL Server版本,它們會被翻譯成Top n子句。

TakeWhile和SkipWhile

參數(shù)

類型

Source sequence

IEnumerable<TSource>

Predicate

TSource   => bool or (TSource,int) => bool

TakeWhile遍歷輸入sequence,返回每個element,直到給定的測試條件為false,然后忽略剩下的elements:

            int[] numbers = { 3, 5, 2, 234, 4, 1 };
var takeWhileSmall = numbers.TakeWhile(n => n < 100); // { 3, 5, 2 }

SkipWhile遍歷輸入sequence,忽略每個element,直到給定的測試條件為false,然后返回剩下的elements:

            int[] numbers = { 3, 5, 2, 234, 4, 1 };
var skipWhileSmall = numbers.SkipWhile(n => n < 100); // { 234, 4, 1 }

TakeWhile和SkipWhile沒有對應的SQL翻譯,如果在LINQ-to-db查詢中使用他們會導致運行時錯誤。

Distinct

Distinct返回去除了重復元素之后的輸入sequence,在確定元素是否重復時只能使用默認的相等比較方法:

            // The following returns distinct letters in a string
char[] distinctLetters = "HelloWorld".Distinct().ToArray();
string s = new string (distinctLetters); // HeloWrd

我們可以在string變量上直接調(diào)用LINQ方法,因為string實現(xiàn)了IEnumerable<char>。

來源:https://www./content-4-274551.html

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多