I seem to be missing something about LINQ. To me, it looks like it\'s taking some of the elements of SQL that I like the least and moving them into the C# language and usin
So the really, really big deal about LINQ has nothing to do with Linq to SQL. It's about the enhancements it brought to the C# language itself.
LINQ is not about SQL. LINQ is about being apply functional programming paradigmns on objects.
LINQ to SQL is an ORM built ontop of the LINQ foundation, but LINQ is much more. I don't use LINQ to SQL, yet I use LINQ all the time.
Take the task of finding the intersection of two lists:
Before LINQ, this tasks requires writing a nested foreach that iterates the small list once for every item in the big list O(N*M), and takes about 10 lines of code.
foreach (int number in list1)
{
foreach (int number2 in list2)
{
if (number2 == number)
{
returnList.add(number2);
}
}
}
Using LINQ, it does the same thing in one line of code:
var results = list1.Intersect(list2);
You'll notice that doesn't look like LINQ, yet it is. You don't need to use the expression syntax if you don't want to.
Because linq is really monads in sql clothing, I'm using it on a project to make asynchronous web requests with the continuation monad, and it's proving to work really well!
Check out these articles: 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
From the first article:
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();
});
}
The point is that LINQ integrates your queries into your primary programming language, allowing your IDE to provide you with some facilities (Intellisense and debug support, for example) that you otherwise would not have, and to allow the compiler to type-check your SQL code (which is impossible with a normal string query).
Before:
// 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
After:
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();
Or, alternatively (query syntax):
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 is not just an ORM system, as Jonathan pointed out it brings a lot of functional programming elements to C#. And it lets you do a lot of "database-y" things in regular C# code. It's difficult to explain just how incredibly powerful that can be. Consider how much having solid, well designed generic data structures (such as list, stack, dictionary/hash, etc.) included in common frameworks has improved the state of development in modern languages. Precisely because using these data structures is very common and reducing the intellectual overhead of using them is a huge benefit. LINQ doesn't do anything you can't do yourself, but it makes a lot of operations a lot more straightforward and a lot easier.
Consider the time-honored example of removing duplicates from a non-ordered list. In a lower level language like C or C++ you'd probably have to sort the list and maintain two indices into the list as you removed dupes. In a language with hashes (Java, C#, Javascript, Perl, etc.) you could create a hash where the keys are the unique values, then extract the keys into a new list. With LINQ you could just do this:
int[] data = { 0, 1, 3, 3, 7, 8, 0, 9, 2, 1 };
var uniqueData = data.GroupBy(i => i).Select(g => g.Key);