如何随机读取数据,如何随机排序?
在“SQL时代”我们随机读取一条记录的方法是

1SELECT TOP 1 * FROM TABLE1 ORDER BY NEWID()

当时在LINQ中怎么做?我曾经想当然的用下面的语句,期待他能返回正确的结果

1var customer = (from c in ctx.Customers orderby Guid.NewGuid()).First();

但实际上,LINQ无情地把我那句orderby给过滤掉了,怎么办?难道又要写SQL语句来实现?
假如ORDERBY只是查询条件中的一小部分呢?所有的东西都写成SQL语句?不用!这里有一个小技巧:

1//在自动生成的mapping code中添加
2[Function(Name = "NEWID", IsComposable = true)]
3public Guid NEWID()
4{
5    return ((Guid)(this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))).ReturnValue));
6}

7
8//在使用中
9var customer = (from c in ctx.Customers orderby ctx.NEWID()).First();

如何执行IN操作
在BETA2中,Linq加入了对IN操作的支持,使用起来很简单,把Contains反过来用就可以了

1 string[] tags = new string[] { "aaa""bbb" };
2 var result = from p in ctx.Posts
3              join t in ctx.Tags on p.PostId equals t.PostId
4              where tags.Contains(t.Text)
5              select p;

LINQ会自动帮你生成类似下面的语句

1Text IN ('aaa''bbb')

如何执行LIKE操作
LIKE也是用Contains来实现,只不过需我们手动用循环组合一下,并且……

1 string[] keyWords = new string[] { "aaa""bbb" };
2 var result = from p in ctx.Posts
3              select p;
4  
5 foreach(string keyWord in keyWords)
6 {
7     result = result.Where(p => p.Text.Contains(keyWord));
8 }

LINQ会自动帮你生成类似下面的语句

1Text LIKE @p0 AND Text LIKE @p1@p0=N'%bbb%'@p1=N'%bbb%'

等一下?为什么两个都是bbb?aaa哪儿去了?这是个BUG么?不是!
这是LINQ的运行机制造成的,由于LINQ在最终使用数据之前并不生成SQL语句,只是进行查询条件的组合。由于keyWords以Enumerate的方式Pop出来,LINQ拿到的keyWord只是最后的值。
那我们该怎么办?很简单,一行代码搞定。
 
foreach(string keyWord in keyWords)
{
    
string key = keyWord;
    result 
= result.Where(p => p.Text.Contains(key));
}

看起来很奇怪是吧?但恰恰就是这么一行看似多余的,一个思维正常的程序员平常绝对不会写的代码,起了重大作用。

如何返回业务实体到上层逻辑
几乎所有的Linq教程都是查询然后foreach,甚至可以select匿名类,这在演示中确实是很方便,很酷。但实际应用中,在多层结构流行的今天,谁又会真的这么用呢?我们需要把Linq产生的数据返回给上层,匿名类在这个地方(其他地方,比如逻辑层用来解决一些事情还是比较方便的)除了看起来比较酷以外还有什么其他意义?
LINQ会为我们的数据表、视图生成Table<T>,但实际应用中,我们会把在UI层引用LINQ所在的工程,然后直接使用这个Table<T>么?至少我不会
我们需要把Table转换成我们自己定义的实体(Entity/Model)
select new Entity { ... } 不就完了?没错,但是如果我有类似
GetUserById(Guid UserId)
GetAllUsers()
GetAllActiveUsers()
是不是要在所有方法中,把这个select写一遍?可不可以把这个select独立成一个方法?
像之前所说的,LINQ在最终使用数据之前并不生成SQL语句,也就是说在ToList(), Any(), foreach等等之前,你可以任意的组合,反复地查询,这就给我们独立select方法提供了可能。

 1private IQueryable<Entities.Tag> TranslateToEntity(IQueryable<Tag> tags)
 2{
 3    return from t in tags
 4           select new Entities.Tag
 5           {
 6               TagId = t.TagId,
 7               Text = t.Text,
 8               CreateTime = t.CreateTime
 9           }
;
10}

1List<Entity.Tag> GetAllUsers()
2{
3    //var users = 
4    return TranslateToEntity(users).ToList();
5}

同样的方法适用于分页等一些会在多出使用的操作。
posted on 2007-08-16 17:43  Mirricle  阅读(3254)  评论(11编辑  收藏  举报