Grizzly
Grizzly

Reputation: 5943

The cast to value type 'System.Int32' failed because the materialized value is null. But it works on similar code

In my controller I am searching the database for specific records in an association table.

public ActionResult MyAction(int picId, int myOtherId)
{
    var itemToEdit =
        db.AssocationTable.Single(
            x => x.PropertyId == picId && x.MyForeignKey == myOtherId);

     var myRecord = db.TestTableOne.Find(itemToEdit.PropertyId);

    var lstOfIntsINeed =
        db.AssocationTable.Where(
                x => x.PropertyId == picId && x.MyForeignKey != myOtherId)
            .Select(x => x.MyForeignKey.Value)
            .ToList();

    // the list above, if nothing is found, will give me an empty list where Count == 0
}

Now I am doing the SAME EXACT code but for a different property and I am receiving:

The cast to value type 'System.Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

Here is my code for that:

public ActionResult MyOtherAction(int picId, int myOtherId)
{
    var itemToEdit =
        db.AssociationTable.Single(
            x => x.PropertyId == picId && x.MyOtherForeignKey == myOtherId);

    var myMainRecord = db.TestTableOne.Find(itemToEdit.PropertyId);

    var lstOfIntsINeed =
        db.AssociationTable.Where(
                x => x.PropertyId == picId && x.MyOtherForeignKey != myOtherId)
            .Select(x => x.MyOtherForeignKey.Value)
            .ToList();
}

In both my database and my Domain Model Class for my Association Table both MyForeignKey and MyOtherForeignKey are nullable:

    [ForeignKey("TestTableTwo")]
    public int? MyForeignKey { get; set; }

    [ForeignKey("TestTableThree")]
    public int? MyOtherForeignKey { get; set; }

So, my question.. why in the first ActionResult is the lst receiving a count of 0 (which is what I expect), and the second ActionResult is receiving the exception error?

Upvotes: 1

Views: 8789

Answers (1)

Trevor
Trevor

Reputation: 1271

I think the problem is that you are calling .Value on your nullable int without checking it for null first. Ultimately it means you are performing a narrowing implicit conversion in the middle of the query.

If the code were to be run in .NET, and the x.MyOtherForeignKey was null, it would throw a Nullable object must have a value exception. In this case, the code is being converted into a Linq-to-Sql expression and run in EntityFramework. I think it's finding a null x.MyOtherForeignKey in your second query and giving this exception.

Depending on what you want the code to do when it encounters a null, you could change it to filter out the nulls:

var lstOfIntsINeed =
    db.AssociationTable.Where(
            x => x.PropertyId == picId && x.MyOtherForeignKey != myOtherId && x.MyOtherForeignKey != null)
        .Select(x => x.MyOtherForeignKey.Value)
        .ToList();

... or to replace the null with a default value.

I think the same problem exists in your first query as well, and the only reason that it didn't fail in your tests is because the query returns no entries (or more specifically, no entries with a null MyForeignKey), so it hasn't failed.

Given that you've defined MyForeignKey as nullable, you must be considering a situation where it is null, so it would be sensible to fix it in that query too.

You could test to see if this was the case by changing the .Where() clause to deliberately return AssociationTable entries with null values.

Hope this helps

Upvotes: 1

Related Questions