我似乎遗漏了一些关于 LINQ 的东西。对我来说,它看起来像是将一些我最不喜欢的 SQL 元素转移到 C# 语言中,并将它们用于其他事情。
我的意思是,我可以看到在数据库以外的事物上使用类似 SQL 的语句的好处。但是,如果我想编写 SQL,那么为什么不直接编写 SQL 并将其排除在 C# 之外呢?我在这里想念什么?
LINQ 与 SQL 无关。LINQ 是关于在对象上应用函数式编程范例。
LINQ to SQL 是建立在 LINQ 基础之上的 ORM,但 LINQ 远不止于此。我不使用 LINQ to SQL,但我一直使用 LINQ。
以查找两个列表的交集为任务:
在 LINQ 之前,此任务需要编写一个嵌套的 foreach,它为大列表中的每个项目迭代一次小列表 O(N*M),并且需要大约 10 行代码。
foreach (int number in list1)
{
foreach (int number2 in list2)
{
if (number2 == number)
{
returnList.add(number2);
}
}
}
使用 LINQ,它在一行代码中做同样的事情:
var results = list1.Intersect(list2);
您会注意到它看起来不像 LINQ,但它确实如此。如果您不想,则不需要使用表达式语法。
前:
// Init Movie
m_ImageArray = new Image[K_NB_IMAGE];
Stream l_ImageStream = null;
Bitmap l_Bitmap = null;
// get a reference to the current assembly
Assembly l_Assembly = Assembly.GetExecutingAssembly();
// get a list of resource names from the manifest
string[] l_ResourceName = l_Assembly.GetManifestResourceNames();
foreach (string l_Str in l_ResourceName)
{
if (l_Str.EndsWith(".png"))
{
// attach to stream to the resource in the manifest
l_ImageStream = l_Assembly.GetManifestResourceStream(l_Str);
if (!(null == l_ImageStream))
{
// create a new bitmap from this stream and
// add it to the arraylist
l_Bitmap = Bitmap.FromStream(l_ImageStream) as Bitmap;
if (!(null == l_Bitmap))
{
int l_Index = Convert.ToInt32(l_Str.Substring(l_Str.Length - 6, 2));
l_Index -= 1;
if (l_Index < 0) l_Index = 0;
if (l_Index > K_NB_IMAGE) l_Index = K_NB_IMAGE;
m_ImageArray[l_Index] = l_Bitmap;
}
l_Bitmap = null;
l_ImageStream.Close();
l_ImageStream = null;
} // if
} // if
} // foreach
后:
Assembly l_Assembly = Assembly.GetExecutingAssembly();
//Linq is the tops
m_ImageList = l_Assembly.GetManifestResourceNames()
.Where(a => a.EndsWith(".png"))
.OrderBy(b => b)
.Select(c => l_Assembly.GetManifestResourceStream(c))
.Where(d => d != null) //ImageStream not null
.Select(e => Bitmap.FromStream(e))
.Where(f => f != null) //Bitmap not null
.ToList();
或者,或者(查询语法):
Assembly l_Assembly = Assembly.GetExecutingAssembly();
//Linq is the tops
m_ImageList = (
from resource in l_Assembly.GetManifestResourceNames()
where resource.EndsWith(".png")
orderby resource
let imageStream = l_Assembly.GetManifestResourceStream(resource)
where imageStream != null
let bitmap = Bitmap.FromStream(imageStream)
where bitmap != null)
.ToList();
所以关于 LINQ 的真正重要的事情与 Linq to SQL 无关。这是关于它为 C# 语言本身带来的增强。
LINQ 不仅仅是一个 ORM 系统,正如 Jonathan 指出的那样,它为 C# 带来了许多函数式编程元素。它可以让你在常规 C# 代码中做很多“数据库-y”的事情。很难解释它的强大程度。考虑在通用框架中包含可靠、设计良好的通用数据结构(如列表、堆栈、字典/哈希等)在多大程度上改善了现代语言的开发状态。正是因为使用这些数据结构非常普遍,并且减少使用它们的智力开销是一个巨大的好处。LINQ 不会做任何你自己做不到的事情,但它让很多操作变得更直接、更容易。
考虑从无序列表中删除重复项的历史悠久的例子。在像 C 或 C++ 这样的较低级别的语言中,您可能必须对列表进行排序并在删除重复项时在列表中维护两个索引。在具有散列的语言(Java、C#、Javascript、Perl 等)中,您可以创建一个散列,其中键是唯一值,然后将键提取到新列表中。使用 LINQ,您可以这样做:
int[] data = { 0, 1, 3, 3, 7, 8, 0, 9, 2, 1 };
var uniqueData = data.GroupBy(i => i).Select(g => g.Key);
因为 linq 确实是 sql 服装中的 monad,所以我在一个项目中使用它来使用 continuation monad 发出异步 Web 请求,并且证明它工作得非常好!
查看这些文章: http : //www.aboutcode.net/2008/01/14/Async+WebRequest+Using+LINQ+Syntax.aspx http://blogs.msdn.com/wesdyer/archive/2008/01/ 11/the-marvels-of-monads.aspx
从第一篇文章:
var requests = new[]
{
WebRequest.Create("http://www.google.com/"),
WebRequest.Create("http://www.yahoo.com/"),
WebRequest.Create("http://channel9.msdn.com/")
};
var pages = from request in requests
select
from response in request.GetResponseAsync()
let stream = response.GetResponseStream()
from html in stream.ReadToEndAsync()
select new { html, response };
foreach (var page in pages)
{
page(d =>
{
Console.WriteLine(d.response.ResponseUri.ToString());
Console.WriteLine(d.html.Substring(0, 40));
Console.WriteLine();
});
}
关键是 LINQ 将您的查询集成到您的主要编程语言中,允许您的 IDE 为您提供一些您原本不会拥有的功能(例如 Intellisense 和调试支持),并允许编译器对您的 SQL 进行类型检查代码(这对于普通的字符串查询是不可能的)。