兴国安邦

C# 3.0, Linq, Linq To Sql

博客园 首页 新随笔 联系 订阅 管理
  33 Posts :: 0 Stories :: 553 Comments :: 150 Trackbacks
有这么一个例子,寻找一个表中的某个字段介于某个给定的集合该怎么办?Sql写起来很简单,比如:Select * from table where id in (2,3, 4, 5)。 就是寻找id字段为这个给定的集合(2,3, 4, 5)内的值。那Linq to Sql该怎么做呢?一个字,简单。

In Operator 
比如,我们想要查找,"AROUT", "BOLID" 和 "FISSA" 这三个客户的订单。该如何做呢?Linq to Sql是这么做的。
        string[] customerID_Set = new string[] { "AROUT", "BOLID", "FISSA" };

        
var q = (from o in db.Orders
                 
where customerID_Set.Contains(o.CustomerID)
                 
select o).ToList();
其生成的sql语句为
SELECT [t0].[OrderID][t0].[CustomerID][t0].[EmployeeID][t0].[OrderDate][
t0
].[RequiredDate][t0].[ShippedDate][t0].[ShipVia][t0].[Freight][t0].[Sh
ipName
][t0].[ShipAddress][t0].[ShipCity][t0].[ShipRegion][t0].[ShipPosta
lCode
][t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[CustomerID] IN (@p0@p1@p2)
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [AROUT]
--
 @p1: Input String (Size = 5; Prec = 0; Scale = 0) [BOLID]
--
 @p2: Input String (Size = 5; Prec = 0; Scale = 0) [FISSA]
先定义了一个数组,在linq query中,使用Contains,也很好理解,就是这个数组,包含了所有的CustomerID, 即返回结果中,所有的CustomerID都在这个集合内。也就是in。 你也可以把数组的定义放在linq语句里。比如:
        var q = (from o in db.Orders
                 
where (new string[] { "AROUT", "BOLID", "FISSA" }).Contains(o.CustomerID)
                 
select o).ToList();
Not in 呢?加个取反就是
        var q2 = (from o in db.Orders
                 
where !(new string[] { "AROUT", "BOLID", "FISSA" }).Contains(o.CustomerID)
                 
select o).ToList();
就这么简单。

Like Operator
Like的操作,有点像in,但是,方向变了。什么意思呢。就是你给定一个字符串,去寻找数据中某个字段包含这个字符串。就是给定的字符串是某字段的子集。Sql Script是这么写的。
Selec * from table where id like '%AD%'
Selec 
* from table where id like '%AD'
Selec 
* from table where id like 'AD%'
上面的%是通配符,表示,该字段含有某个值,不知道的位置使用%代替。第一个是表示中间一段是AD,两头不清楚。第二个是结尾是AD,前面的不清楚。第三个相反,开头是AD,结尾不清楚。其对应的Linq 语句为
        var q = (from c in db.Customers
                 
where c.CustomerID.Contains("ROUT")
                 
select c).ToList();
其生成的sql为
SELECT [t0].[CustomerID][t0].[CompanyName][t0].[ContactName][t0].[ContactT
itle
][t0].[Address][t0].[City][t0].[Region][t0].[PostalCode][t0].[Coun
try
][t0].[Phone][t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 6; Prec = 0; Scale = 0) [%ROUT%]
以ISSA结尾,头部通配:
        var q = (from c in db.Customers
                 
where c.CustomerID.EndsWith("ISSA")
                 
select c).ToList();
其生成的sql为
SELECT [t0].[CustomerID][t0].[CompanyName][t0].[ContactName][t0].[ContactT
itle
][t0].[Address][t0].[City][t0].[Region][t0].[PostalCode][t0].[Coun
try
][t0].[Phone][t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [%ISSA]
以ARO开始,尾部通配:
        var q = (from c in db.Customers
                 
where c.CustomerID.StartsWith("ARO")
                 
select c).ToList();
其生成的sql为
SELECT [t0].[CustomerID][t0].[CompanyName][t0].[ContactName][t0].[ContactT
itle
][t0].[Address][t0].[City][t0].[Region][t0].[PostalCode][t0].[Coun
try
][t0].[Phone][t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 4; Prec = 0; Scale = 0) [ARO%]

Linq 还提供了一种方法,叫做SqlMethods.Like,需要先添加System.Data.Linq.SqlClient名称空间。上面的三个可以写成
       var q = (from c in db.Customers
                 
where SqlMethods.Like(c.CustomerID, "%ROUT%")
                 
select c).ToList();
这里,你需要自己填写通配符,告诉Linq你是如何匹配。比如
        var q = (from c in db.Customers
                 
where SqlMethods.Like(c.CustomerID, "%ISSA")
                 
select c).ToList();
再比如:
        var q = (from c in db.Customers
                 
where SqlMethods.Like(c.CustomerID, "ARO%")
                 
select c).ToList();
SqlMethods.Like最奇妙的地方,莫过于,自己定义的通配表达式,你可以在任何地方实现通配。比如
        var q = (from c in db.Customers
                 
where SqlMethods.Like(c.CustomerID, "A%O%T")
                 
select c).ToList();
其生成的sql为
SELECT [t0].[CustomerID][t0].[CompanyName][t0].[ContactName][t0].[ContactT
itle
][t0].[Address][t0].[City][t0].[Region][t0].[PostalCode][t0].[Coun
try
][t0].[Phone][t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [A%O%T]

就是最标准的知道以A开头,以T结尾,中间知道一个值O,其他就什么不知道了。就用这个。
SQL Server 定义了四种通配符,在这里都可以使用。它们是:
Wildcard character Description Example
% Any string of zero or more characters. WHERE title LIKE '%computer%' finds all book titles with the word 'computer' anywhere in the book title.
_ (underscore) Any single character. WHERE au_fname LIKE '_ean' finds all four-letter first names that end with ean (Dean, Sean, and so on).
[ ] Any single character within the specified range ([a-f]) or set ([abcdef]). WHERE au_lname LIKE '[C-P]arsen' finds author last names ending with arsen and beginning with any single character between C and P, for example Carsen, Larsen, Karsen, and so on.
[^] Any single character not within the specified range ([^a-f]) or set ([^abcdef]). WHERE au_lname LIKE 'de[^l]%' all author last names beginning with de and where the following letter is not l.

%表示零长度或任意长度的字符串。_表示一个字符。[]表示在某范围区间的一个字符。[^]表示不在某范围区间的一个字符
比如:
        var q = (from c in db.Customers
                 
where SqlMethods.Like(c.CustomerID, "A_O_T")
                 
select c).ToList();
就用_代表一个字符。其生成sql为
SELECT [t0].[CustomerID][t0].[CompanyName][t0].[ContactName][t0].[ContactT
itle
][t0].[Address][t0].[City][t0].[Region][t0].[PostalCode][t0].[Coun
try
][t0].[Phone][t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [A_O_T]

对于Not Like,也很简单,加个取非就是。
        var q = (from c in db.Customers
                 
where !SqlMethods.Like(c.CustomerID, "A_O_T")
                 
select c).ToList();

SqlMethods.Like还有一个参数,叫escape Character,其将会被翻译成类似下面的语句。
SELECT columns FROM table WHERE 
    
column LIKE '%\%%' ESCAPE '\'
escape 是因为某字段中含有特殊字符,比如%,_ [ ]这些被用作通配符的。这时就要用到Escape了。这是sql server的事情了。详细情况请参考:
http://msdn2.microsoft.com/en-us/library/Aa933232(SQL.80).aspx
posted on 2007-08-01 20:34 Tom Song 阅读(5567) 评论(22)  编辑 收藏 网摘 所属分类: C# 3.0Linq To Sql

Feedback

收下,仔细研究。
  回复  引用    

#2楼 2007-08-01 20:44 永红      
还没有用过3.0,这样看来ORM快失业了。
  回复  引用  查看    

#3楼 2007-08-01 20:46 随风流月      
@永红
可以这样说。不过 LINQ to SQL 目前的数据库兼容性不够。
@宋国安
本地 Collection 其实是很有意思的,有的时候又出错,什么“Query with Local Collections”之类的东西。

  回复  引用  查看    

#4楼 2007-08-01 21:28 zzz[未注册用户]
这些东西只要对SQL有所了解就很好懂了。。。
楼主继续努力

  回复  引用    

#5楼 2007-08-01 22:13 Young18
@永红
ORM快失业了?Dlinq就是orm,应该是推动orm的发展!微软一直在做orm的尝试,这次动真格的了

  回复  引用    

谢谢!其他已经熟悉了,主要是 SqlMethods.Like 之前没看到过 :)

  回复  引用  查看    

#7楼 2007-08-01 22:28 宋国安
@木野狐(Neil Chen)
SqlMethods类下,不光有like,还有其他好多函数。你可以根据它们的定义一一尝试下。全部可以转化为sql server中的对应操作。研究清楚了,可以写个文章给大家分享。

  回复  引用    

#8楼 2007-08-01 23:21 ˇ┾落≠單_      
LZ错了.
简单已是两个字.

应该是 easy.

  回复  引用  查看    

#9楼[楼主] 2007-08-02 08:02 宋国安      
@ˇ┾落≠單_
不懂弟兄的幽默方式....
哈哈。
好吧,两个字。

  回复  引用  查看    

#10楼 2007-08-02 09:28 Anders Liu      
我想还是 SqlMethods.Like 比较靠谱,这应该能被翻译成对应的sql语句。而直接用Contains、StartWith、EndWith不知道还能不能翻译成sql语句放到数据库服务器上执行。

希望lz能进一步给出所有这些例子生成的sql语句。

  回复  引用  查看    

#11楼 2007-08-02 09:40 Young18
@Anders Liu
显示Linq语句编译后的Sql语句的方法
方法1:用DataContext的Log属性。db.Log = Response.Output;
方法2:用GetQueryText / GetChangeText。GetQueryText用于查询时使用,GetChangeText用于更新或删除。
http://www.cnblogs.com/young18/archive/2007/06/17/786651.html

  回复  引用    

#12楼 2007-08-02 09:59 随风流月      
@Anders Liu
Contains 可以翻译为 '%Query%'
StartWith 可以翻译为 'Query%'
EndWith 可以翻译为 '%Query'
其实 VB 最舒服,根本用不到 SQLMethod.Like,直接拥有 Like 运算符。

  回复  引用  查看    

#13楼 2007-08-02 09:59 随风流月      
@Anders Liu
还有一点,大规模插入数据时不建议用 LINQ,效率非常低下。
速度和 StringBuilder + ADO.Net 没法比了。

  回复  引用  查看    

#14楼[楼主] 2007-08-02 12:12 宋国安      
@Anders Liu
已经按你的要求更新。方便大家比较。

@随风流月
是的,大规模插入数据不是Linq所擅长的。

  回复  引用  查看    

#15楼 2007-08-02 23:34 hiber[未注册用户]
@ 宋国安
是的,大规模插入数据不是Linq所擅长的。

是不是少打了一个D啊,呵呵

  回复  引用    

这个可以么!!!!
  回复  引用    

#17楼[楼主] 2007-08-28 11:35 宋国安      
re: C#3.0入门系列(五)-之Where操作[未登录]2007-08-09 11:27 | chen

请问如下sql语句用linq怎么写
select * from tableA where tableA.name like '%abc%'
and tableA.id not in
(select tableB.aid from tableB wher tableB.name like '%1234%') 回复 更多评论
删除评论
# re: C#3.0入门系列(五)-之Where操作2007-08-09 15:55 | 宋国安

var q1 = (from c in db2.Customers
where SqlMethods.Like(c.CustomerID, "A%O%T")
&& !(from d in db2.Customers
where SqlMethods.Like(d.CustomerID, "BOLID")
select d.CustomerID
).Contains(c.CustomerID)
select c).ToList(); 回复 更多评论
删除评论 修改评论

  回复  引用  查看    

var q = (from c in db.Customers
where c.CustomerID.Contains("ROUT")
select c).ToList();
我用这语句的时候报如下异常
Sequence operators not supported for type 'System.String'
我的版本是vs2008beta2带的.net framework 3.5,是不是新版本变了?

  回复  引用    

请问:

动态LINQ to SQL(System.Linq.Dynamic库)中的like的对应语句是Contains吗?能否给个示范例子,谢谢!

  回复  引用    

#20楼 2008-04-09 14:04 Vincent Love      
--引用--------------------------------------------------
随风流月: @Anders Liu
还有一点,大规模插入数据时不建议用 LINQ,效率非常低下。
速度和 StringBuilder + ADO.Net 没法比了。
--------------------------------------------------------

那为什么MS还要推出linq呢,难道一个项目里面既要用sql,又要用linq吗

  回复  引用  查看    

#21楼 2008-04-24 17:57 rex xiang      
System.Data.Linq.SqlClient.SqlMethods.Like(string, string)

Summary:
Throws a System.NotSupportedException always.

Parameters:
matchExpression: The string to be searched for a match.
pattern: The pattern, which may include wildcard characters, to match in matchExpression.

Return Values:
true if matchExpression matches the pattern; otherwise, false.
----------

System.Reflection.AssemblyFileVersionAttribute("3.5.21022.8")
System.Reflection.AssemblyInformationalVersionAttribute("3.5.21022.8")

请教一下, 为什么我看到的版本, 已经是"Throws a System.NotSupportedException always"了?

  回复  引用  查看    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 839448




相关文章:

相关链接: