Visual Studio 2008 In Action 之 Linq,一些操作

在“SQL时代”我们随机读取一条记录的方法是

 

SELECT TOP 1 * FROM TABLE1 ORDER BY NEWID()


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

 

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


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

 

//在自动生成的mapping code中添加
[Function(Name = "NEWID", IsComposable = true)]
public Guid NEWID()
{
    
return ((Guid)(this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))).ReturnValue));
}
//在使用中
var customer = (from c in ctx.Customers orderby ctx.NEWID()).First();


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

 

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


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

 

Text IN ('aaa''bbb')


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

 

string[] keyWords = new string[] { "aaa""bbb" };
var result 
= from p in ctx.Posts
              select p;
  
foreach(string keyWord in keyWords)
{
    result 
= result.Where(p => p.Text.Contains(keyWord));
}


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

 

Text 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方法提供了可能。

 private IQueryable<Entities.Tag> TranslateToEntity(IQueryable<Tag> tags)
 {
    
return from t in tags
            select 
new Entities.Tag
           {
               TagId 
= t.TagId,
              Text 
= t.Text,
               CreateTime 
= t.CreateTime
           };
}
List
<Entity.Tag> GetAllUsers()
{
   
//var users = 
    return TranslateToEntity(users).ToList();
}


同样的方法适用于分页等一些会在多出使用的操作。

posted on 2007-11-02 12:56  jueban's space  阅读(273)  评论(0)    收藏  举报

导航