谈Linq To Sql的优劣--纯个人观点

Linq To Sql是Microsoft开发的针对解决data!=object问题的新技术。在笔者的一系列的文章中,对它已经做了大量的介绍。现在,笔者将从经验的角度,谈谈它的优劣.

1,Linq To Sql的优点
在Linq To Sql推出之前,我们只是把sql语句形成一个string,然后,通过ado.net传给sql server,返回结果集.这里的缺陷就是,如果你sql语句写的有问题,只有到运行时才知道.而且并不所有的人都懂数据库的。Linq To SQl 在一切围绕数据的项目内都可以使用。特别是在项目中缺少sql server方面的专家时,Linq To SQl的强大的功能可以帮我们快速的完成项目。Linq To SQl的推出,是让大家从烦琐的技术细节中解脱出来,更加关注项目的逻辑.Linq To Sql的出现,大大降低了数据库应用程序开发的门楷,它实质是事先为你构架了数据访问层,势必将加快数据库应用程序的开发进度。Linq To Sql解放了众多程序员,让他们的把更多的精力放到业务逻辑以及code上,而不是数据库。对于初学者来讲,Linq To Sql可以让他们迅速进入数据库应用程序开发领域,节约了培训成本。

Linq To SQl 的实现,是在ado.net和c#2.0的基础上的。它通过自动翻译sql语句,并把结果集创建成对象并返回。这里我们可以看出,发送到Sql Server端的sql语句是Linq To Sql自动生成的。这对不懂sql的人来说,无疑是个福音.第二,Linq To Sql语句是在编译期间就做检查的。而不是运行时检查。这样,那里出了问题,可以及时更改,而不是到了运行时才发现问题。第三, Linq To Sql是针对对象操作的,更符合今天的oo呼声。

在Linq To SQl 之前,在java领域有Hibernate,在net领域有NHibernate技术,来实现object/relational 持久和查询服务。那和NHibernate比起来,它又有那些优势呢.第一,影射代码自动生成。VS2008提供了SqlMetal和OR Designer两个工具来完成此步骤。而在NHibernate中,你不得不自己手工写。第二,影射代码有更多的选择.NHibernate只能把数据库的信息配置在一个xml中,而Linq To Sql有两种方式,一个是放到xml中,我们称为Externl Mapping, 再一种就是以Attribute的形式,存在于各个property中。当然,笔者本人并没有使用过NHibernate,只是从资料上得到这些消息,所以无法给出更多的比较。

2,Linq To Sql的缺点
很久前,有个网友问到这么一个问题。 他在界面上,有个DataView,里面绑定了一些Column,然后,他勾选那一列,就按某列排序。其传回的参数是列的名字。然后问我,该怎么用Dlinq 来实现。
在以前拼接Sql语句的年代,这个很简单,一个" order by " + string,想按什么排就按什么来排。而现在,dlinq是用是一个对象的属性,已经不可能拼接了。我当时给他的答案是这样的。
private void Methods(string orderId)
{
    var q 
= db.Customers.Select(c=>c);

    
switch(orderId)
    
{
        
case "ID":
            q 
= q.OrderBy(c=>c.ID);
            
break;
        
case "Name":
            q 
= q.OrderBy(c=>c.Name);
            
break;
        
default:
            
break;
    }

    
    var result 
= q.ToList();
}

我那时也没有想出一个更好的方案来。而后告诉他,去查下Compiled Query.说不定,可以找到更方便的。后来我才在这个例子中,看到更方便的。
            var query =
                db.Customers.Where(
"City == @0 and Orders.Count >= @1""London"10).
                OrderBy(
"CompanyName").
                Select(
"New(CompanyName as Name, Phone)");
在这里OrderBy直接接收的就是列的名字。再仔细一看,好像Where里是Linq的语句哎,那OrderBy也该是linq语句。后来,我把CompanyName换成小写的,一跑过了。莫非真的是列的名字?出个难题吧。找了一个列名,是带空格的,重新来建这个工程.一跑,错了!把列名用中国扩号扩起来了,也是错了。咳,只是动态构造Expression Tree而已,永远都不能直接接收列的名字。这个例子看着是很简单,可不知道你有没有注意到它有一个80多k的Dynamic.cs文件。更有意思的事情是,它的名称空间是System.Linq.Dynamic.看样子,ms本来是打算把它加在.net 3.5中吗.不晓得为什么放到了例子中了。这个名称空间下,其主要内容就是动态构造Expression Tree. 和Linq To Sql进阶系列(七)动态查询 一文中的方法类似。只是,它还包含了解析字符串部分.

从上面那个例子中,可以看出,Linq To Sql在这种动态构造语句时,比拼接sql麻烦很多。在Linq To Sql进阶系列(七)动态查询 一文中,笔者极力推荐使用object的查询。这符合Linq To Sql的设计原则。因为,它主要是为了解决data!=objects 的问题而产生的.它所有的操作均针对object,那就让我们使用object的查询吧.
当然,依然会有人习惯拼接字符串.我并不认为这是个坏毛病。只是有点不符合oo思想而已。事实上,在Linq To Sql中,你依然可以使用拼接字符串的形式,而不使用它提供的Query Expression. 它提供了这么两个接口,一个是,db.ExecuteQuery<TEntity>(string sql); 另一个是,db.ExecuteCommand(string sql);这两个函数都是直接接收 sql语句的.习惯拼接的人,依然可以调用它们来实现你的程序。特别是第一个,其返回的就是一个对象的集合,多少还是有点oo思想的。

看下面的例子,

    var products = db.ExecuteQuery<Product>(
      &nb