技术开发 频道

LINQ 未满


  对于我的 DbEntry.Net,我对于查询最大的遗憾就是,没有办法象原生查询那样直接写变量,而要把字段名写成字符串,不过,即使在像 db4o 这种对象数据库中,对于非原生查询的字段名,也是使用的字符串,其实也就是没有什么好的办法就是了。

  不过,在 .Net 3.0 里,有了表达式树,对于类原生查询的语法,也可以延迟计算,那么就可以突破这个限制了。

  回到 LINQ。在 LINQ 中,对于数据库的查询,可以使用完全的类 SQL 语法:
1. // DataContext takes a connection string 2. DataContext db = new DataContext("c:\\northwind\\northwnd.mdf"); 3. // Get a typed table to run queries 4. Table<Customer> Customers = db.GetTable<Customer>(); 5. // Query for customers from London 6. var q = 7. from c in Customers 8. where c.City == "London" 9. select c; 10. foreach (var cust in q) 11. Console.WriteLine("id = {0}, City = {1}", cust.CustomerID, cust.City);
  而其中的 from ... where ... select 语法到 lambda 语法的转换,是编译器在做的,我讨厌这个限定。

  首先,from、select、orderby 根本不应该成为 c# 或 vb.net 的关键字;其次,这使得,除了 SQL 语句,我们定义的其他 DSL,都要使用比较丑陋的 lambda 语法。SQL 只是 DSL 的一种,我觉得,无限夸大它在 C# 中的作用并不是一个好现象。

  事实上,我觉得可以做一个类似 xml 中 CDATA 的语法来进行 DSL 的扩展:
1. // DataContext takes a connection string 2. DataContext db = new DataContext("c:\\northwind\\northwnd.mdf"); 3. // Get a typed table to run queries 4. Table<Customer> Customers = db.GetTable<Customer>(); 5. // Query for customers from London 6. var q = <![DSL.SQL[ 7. from c in Customers 8. where c.City == "London" 9. select c]]>; 10. foreach (var cust in q) 11. Console.WriteLine("id = {0}, City = {1}", cust.CustomerID, cust.City);
  这只是随便写的,可能并不是无歧意的,不过,我要表明的是,进行类似这样的语法构造后,定义 DSL 将是一件轻松而愉快的工作,而且,C# 将是一种 DSL 的创造者,而不是只和 SQL 绑定的。虽然通用的 DSL 仍然需要某些大的国际组织进行标准化,不过,第三方可开发的 DSL,将是一个很好的推动力。(DSL 也并不一定是文本格式的,比如 UML,不过,大部分还是文本格式为主)

  既然 C# 3.0 已经是 SQL 绑定的,对于通用 DSL 定义,我们是否应该寄希望于 C# 4.0?可是,在 C# 3.0 中,from、select、orderby 已经成为 C# 的关键字,不可能在新版本中取消,那么结果会是什么?SQL 是唯一一种特化 DSL?

  好的,LINQ 是直观的,不过,有时候,直观不一定是好事。举一个常见的例子吧,一个高级查询页面,用户可以选择填写“标题”、或者填写“内容”,或者两者都填写,以便决定进行什么样的查询,使用 DbEntry.Net 的查询方式是这样的:
1. using org.hanzify.llf.Data; 2. 3. public class DbAccess 4. { 5. public DbItemList<News> Query(string Title, string Content) 6. { 7. IWhereClause iwc = null; 8. if ( Title != null && Title != "" ) 9. { 10. iwc &= CK.K["Title"] ^ "%" + Title + "%"; 11. } 12. if ( Content != null && Content != "" ) 13. { 14. iwc &= CK.K["Content"] ^ "%" + Title + "%"; 15. } 16. if ( iwc == null ) 17. { 18. throw new Exception("条件不能都是空的!"); 19. } 20. return new DbItemList<News>(iwc); 21. } 22. }
0
相关文章