4

Take this:

int? item1 = null;
int? item2 = null;

someObjectList.Where(x => x.SomeItem1 == (item1 ?? x.SomeItem1)
                       && x.SomeItem2 == (item2 ?? x.SomeItem2) 
                    );

Where someObjectList is not empty and SomeItem1 and SomeItem2 is null in all the objects in the list.

Why is it returning nothing?

EDIT:

My Code:

public void GetPlacementsByMaterial(long clientMaterialID)
{
    ClientMaterial clientMaterial = ((ApplicationEntityModel)NavigationItem.ObjectContext).ClientMaterial.FirstOrDefault(x => x.ClientMaterialID == clientMaterialID);

    var list = GetPlacementList(supplier, mediaSpace);

    PlacementsList = list.Where(x => x.MediaCategoryFormatID == (clientMaterial.MediaCategoryFormatID ?? x.MediaCategoryFormatID)
                                                && x.MediaCategorySizeID == (clientMaterial.MediaCategorySizeID ?? x.MediaCategorySizeID) 
                             );
}

All ID's are Nullable<long>.

EDIT:

SQL Profiler:

SELECT *
  FROM [dbo].[CampaignSchedulePlacements] AS [Extent5]
WHERE ([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID]) AND ([Extent5].[MediaCategorySizeID] = [Extent5].[MediaCategorySizeID])

Note: cleaned up the `SQL.

Willem
  • 9,166
  • 17
  • 68
  • 92
  • 5
    Please post a full example that reproduces the problem. – CodesInChaos Jul 21 '12 at 17:21
  • It works fine for me. What's the type of `SomeItem1`? Does it have an overloaded `==` operator? – Ry- Jul 21 '12 at 17:22
  • What's the type of `list`? Are you using Linq-To-Objects, or some `IQueryable` stuff? – CodesInChaos Jul 21 '12 at 17:29
  • @CodesInChaos Using Linq-to-entities and it's all basic queries. Nothing fancy. All the objects are of type `EntityObject`. I just cant seem to work it out... – Willem Jul 21 '12 at 17:34
  • 1
    You're using Linq to Entities. Look at the actual SQL generated using the debugger (e.g. in Intellitrace). – Kris Vandermotten Jul 21 '12 at 17:34
  • what is actually in the table? as Kris said, if you are comparing NULL to NULL, it will evaluate to false and not return the record, so any record with either a NULL MediaCategoryFormatID or a NULL MediaCategorySizeID will not be returned. – Dave Cousineau Jul 21 '12 at 18:35
  • For completeness, `NULL = NULL` evaluates to unknown, not to false. It matters because `NOT(NULL = NULL)` is not(unknown) (that's still unknown), not not(false) (that's true) –  Jul 21 '12 at 18:45

1 Answers1

5

In SQL, NULL is not equal to NULL.

You can interpret NULL as meaning: "there is value, but I don't know what it is". So if you're comparing two NULL values, you're really asking "is the first unknown value equal to the second unknown value?" Of course, there is no reason to assume they are, so SQL will say "no".

I am assuming that this is causing your problem. You can verify that by looking at the actual SQL produced. If it's using the SQL = operator, this is indeed the problem. You can verify that by running the SQL in a database tool, such as SQL Management Studio in case you're using SQL Server.

UPDATE:

The condition

([Extent5].[MediaCategoryFormatID] = [Extent5].[MediaCategoryFormatID]) 

will indeed return false when [Extent5].[MediaCategoryFormatID] is NULL.

That answers the question "Why is it returning nothing?"

However, another question come to mind: why would the entity framework generate that SQL from this linq query?

I'm afraid that linq to entities is not exactly known for the quality of its SQL generation, and this case seems to confirm that. You might consider Linq to SQL. Even if that seems to be a dead-end track in the long run, the current implementation if a lot better than linq to entities.

In either case, have you tried something like

someObjectList.Where(x => 
    !item1.hasValue || 
    x.SomeItem1.HasValue && x.SomeItem1.Value == item1.Value)

Make sure to verify that under the profiler as well though, linq to entities might mess it up too.

Kris Vandermotten
  • 10,111
  • 38
  • 49
  • Please see my update. I run it on `SQL Profiler`. Any other ideas? – Willem Jul 21 '12 at 18:25
  • Thanks Kris. Sorted. It was `NULL` on both sides of the `==`. – Willem Jul 21 '12 at 18:42
  • 5
    @Willem and Kris: The behaviour is actually an old bug in LINQ to Entities: http://stackoverflow.com/questions/682429/how-can-i-query-for-null-values-in-entity-framework `null == null` is `true` in .NET so it must not be translated directly into a `NULL = NULL` in SQL which is not `true`. It has been fixed for .NET 4.5., so you don't need the workarounds above and in the answers of the linked question anymore in .NET 4.5. – Slauma Jul 21 '12 at 18:54