none
请教一个关于LINQ中判断NULL的问题 RRS feed

  • 问题

  • 请教一个有关在LINQ中搜索NULL的问题。

    大意简化为这样:现在有一个表叫T_01(测试随便起的。。),简单的可以看成是一列Id(int),一列Username (varchar(20))和一列Password(varchar(20)),Password可NULL。由于密码是可空的所以可能存在只有用户名但是没有密码的用户,他们输入用户名就可以直接登录。

    书写这样的LINQ语句可以返回表中所有数据:

    var q_01 = from r in T_01s 
    		  select r;

    但是加入where条件后出现了一个很奇怪的事情:

    var q_02 = from r in T_01s
    		  where r.Password == null
    		  select r;
    
    var q_02_first = q_02.First();

    如果这么写LINQ,直接指定r.Password == null,生成的SQL 语句为

    SELECT TOP (1) [t0].[Id], [t0].[username] AS [Username], [t0].[password] AS [Password]
    FROM [T_01] AS [t0]
    WHERE [t0].[password] IS NULL

    LINQ生成的SQL语句能知道 password 那一列应该是 IS NULL

    但是,如果不指定r.Password == null,而是传一个变量,这个变量为null:

    string strNull = null;
    var q_03 = from r in T_01s
    		  where r.Password == strNull
    		  select r;
    var q_03_count = q_03.Count();

    这时候灵异的事就来了。。LINQ生成的SQL语句成了

    -- Region Parameters
    DECLARE @p0 VarChar(1000) = null
    -- EndRegion
    SELECT COUNT(*) AS [value]
    FROM [T_01] AS [t0]
    WHERE [t0].[password] = @p0
    

    不再是 IS NULL了,而成了password = null

    这样没法搜索出对应的内容……请问有什么办法可以解决么?最好是用户名和密码写在一个LINQ里,先搜用户名取出记录再根据那条记录来看密码是否一样的是下下策了……只是想明白为什么LINQ是因为什么原因不生成 IS NULL 的语句。

    如果用r.Password.Equals(null)和r.Password.Equals(strNull)生成的SQL语句也是,指定了null的生成IS NULL,后者生成 = null ……

    =。=

    现在用三目运算符来解决的,不过非常冗长啊,有没有什么比较便捷的方法或者是我使用方式不对?

    var q_05 = from r in T_01s
    		   where (strNull == null ? (r.Password == null) : (r.Password.Equals(strNull)))
    		   select r;
    
    var q_05_first = q_05.First();

    这样生成的SQL语句成了……

    -- Region Parameters
    DECLARE @p0 Int = 1
    DECLARE @p1 VarChar(1000) = null
    -- EndRegion
    SELECT TOP (1) [t0].[Id], [t0].[username] AS [Username], [t0].[password] AS [Password]
    FROM [T_01] AS [t0]
    WHERE (
        (CASE 
            WHEN @p0 = 1 THEN CONVERT(Int,
                (CASE 
                    WHEN [t0].[password] IS NULL THEN 1
                    ELSE 0
                 END))
            ELSE 
                (CASE 
                    WHEN [t0].[password] = @p1 THEN 1
                    WHEN NOT ([t0].[password] = @p1) THEN 0
                    ELSE NULL
                 END)
         END)) = 1
    

    崩溃。。

    初学LINQ,还请大家帮解答一下,谢谢^^

    2014年1月21日 3:20

答案

全部回复

  • 对于Linq 来说, strNull 还是算变量,本身也可以等于null,它应该不会帮你转换成is null。


    • 已标记为答案 huhubun 2014年1月21日 9:37
    2014年1月21日 3:59
  • 试一下:

    var q_03 = from r in T_01s
    		  where (r.Username == strUsername && r.Password == null) || (r.Username == strUsername && r.Password == strPassword)
    		  select r;

    2014年1月21日 4:17
  • 你好楼主

    >>是想明白为什么LINQ是因为什么原因不生成 IS NULL 的语句。

    因为LINQ对于变量都是会生成@p0,@p1这样的一个参数。楼主你声明的strNull是一个string 类型的变量,但是LINQ不知道它的值会是什么。

    >>不过非常冗长啊,有没有什么比较便捷的方法或者是我使用方式不对?

    楼主可以考虑下使用存储过程:

    http://msdn.microsoft.com/en-us/library/bb386946(v=vs.110).aspx


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • 已标记为答案 huhubun 2014年1月21日 9:37
    2014年1月21日 7:13
    版主
  • 补充Fred Bao - MSFT的回答:

    把存储过程拖拽到LINQ-TO-SQL,应该自动生成一个实体方法,直接调用该方法即可。


    ASP.NET Questions
    Other Discussions
    FreeRice Donate
    Issues to report
    Free Tech Books Search

    • 已标记为答案 huhubun 2014年1月21日 9:37
    2014年1月21日 7:36