背景:在接下来的一个月里,我将做三次关于LINQ的演讲,或者至少将LINQ包含在c#的上下文中。我想知道哪些话题值得花相当多的精力,这取决于人们可能很难理解哪些话题,或者他们可能有错误的印象。我不会具体讨论LINQ to SQL或实体框架,只是作为如何使用表达式树(通常是IQueryable)远程执行查询的示例。
那么,你发现LINQ有什么难的地方吗?在误解方面你看到了什么?例子可能是以下任何一个,但请不要限制自己!
c#编译器如何处理查询表达式
Lambda表达式
表达式树
扩展方法
匿名类型
这个IQueryable
延迟执行与立即执行
流与缓冲执行(例如,OrderBy被延迟但被缓冲)
隐式类型局部变量
读取复杂的泛型签名(例如Enumerable.Join)
我知道延迟执行的概念现在应该被灌输给我了,但这个例子确实帮助我实际掌握了它:
static void Linq_Deferred_Execution_Demo()
{
List<String> items = new List<string> { "Bob", "Alice", "Trent" };
var results = from s in items select s;
Console.WriteLine("Before add:");
foreach (var result in results)
{
Console.WriteLine(result);
}
items.Add("Mallory");
//
// Enumerating the results again will return the new item, even
// though we did not re-assign the Linq expression to it!
//
Console.WriteLine("\nAfter add:");
foreach (var result in results)
{
Console.WriteLine(result);
}
}
上面的代码返回如下:
Before add:
Bob
Alice
Trent
After add:
Bob
Alice
Trent
Mallory
表达式<Func<T1, T2, T3,…>> and Func<T1, T2, T3,…>,没有给出第二个情况下性能下降的提示。
下面是代码示例,演示了我的意思:
[TestMethod]
public void QueryComplexityTest()
{
var users = _dataContext.Users;
Func<User, bool> funcSelector = q => q.UserName.StartsWith("Test");
Expression<Func<User, bool>> expressionSelector = q => q.UserName.StartsWith("Test");
// Returns IEnumerable, and do filtering of data on client-side
IQueryable<User> func = users.Where(funcSelector).AsQueryable();
// Returns IQuerible and do filtering of data on server side
// SELECT ... FROM [dbo].[User] AS [t0] WHERE [t0].[user_name] LIKE @p0
IQueryable<User> exp = users.Where(expressionSelector);
}
如何LINQ到SQL翻译它!
假设我们有一个有3个字段的表;A, B和C(它们是整数,表名为“Table1”)。
我是这样展示的:
[a, b, c]
现在我们想要得到这样的结果:
[x = a, y = b + c]
我们有这样一门课:
public class Temp
{
public Temp(int x, int y)
{
this.X = x;
this.Y = y;
}
public int X { get; private set; }
public int Y { get; private set; }
}
然后我们这样使用它:
using (MyDataContext db = new MyDataContext())
{
var result = db.Table1.Select(row =>
new Temp(row.A, row.B + row.C)).ToList();
}
生成的SQL查询是:
SELECT [t0].[A] AS [x], [t0].[B] + [t0].[C] AS [y]
FROM [Table1] AS [t0]
它转换了Temp的.ctor,它知道我想要“row”。B + row.C”(甚至更多…)放在我的类构造函数的“y”参数上!
我对这些译文很感兴趣。我喜欢这样,我认为编写这样的翻译器(LINQ to Something)有点难!
当然!这是一个坏消息:LINQ to Entities(4.0)不支持带参数的构造函数。(为什么不呢?)