The || (or) Operator in Linq with C#

后端 未结 6 1913
独厮守ぢ
独厮守ぢ 2020-12-06 02:13

I\'m using linq to filter a selection of MessageItems. The method I\'ve written accepts a bunch of parameters that might be null. If they are null, the criteria for the file

6条回答
  •  感动是毒
    2020-12-06 02:40

    If you are using LINQ to SQL, you cannot expect the same C# short-circuit behavior in SQL Server. See this question about short-circuit WHERE clauses (or lack thereof) in SQL Server.

    Also, as I mentioned in a comment, I don't believe you are getting this exception in LINQ to SQL because:

    1. Method String.IsNullOrEmpty(String) has no supported translation to SQL, so you can't use it in LINQ to SQL.
    2. You wouldn't be getting the NullReferenceException. This is a managed exception, it would only happen client-side, not in SQL Server.

    Are you sure this is not going through LINQ to Objects somewhere? Are you calling ToList() or ToArray() on your source or referencing it as a IEnumerable before running this query?


    Update: After reading your comments I tested this again and realized some things. I was wrong about you not using LINQ to SQL. You were not getting the "String.IsNullOrEmpty(String) has no supported translation to SQL" exception because IsNullOrEmpty() is being called on a local variable, not an SQL column, so it is running client-side, even though you are using LINQ to SQL (not LINQ to Objects). Since it is running client-side, you can get a NullReferenceException on that method call, because it is not translated to SQL, where you cannot get a NullReferenceException.

    One way to make your solution seem less hacky is be resolving fromname's "null-ness" outside the query:

    string lowerfromname = String.IsNullOrEmpty(fromname) ? fromname : fromname.ToLower();
    
    var messages = from msg in dc.MessageItems
                   where String.IsNullOrEmpty(lowerfromname) || msg.Name.ToLower().Contains(lowerfromname)
                   select msg.Name;
    

    Note that this will not always be translated to something like (using your comments as example):

    SELECT ... FROM ... WHERE @theValue IS NULL OR @theValue = theValue
    

    Its translation will be decided at runtime depending on whether fromname is null or not. If it is null, it will translate without a WHERE clause. If it is not null, it will translate with a simple "WHERE @theValue = theValue", without null check in T-SQL.

    So in the end, the question of whether it will short-circuit in SQL or not is irrelevant in this case because the LINQ to SQL runtime will emit different T-SQL queries if fromname is null or not. In a sense, it is short-circuited client-side before querying the database.

提交回复
热议问题