Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null property in object recovered by EF

I'm having trouble pulling a ApplicationUser object in a query to the DbContext.

Here is my Foo model

public class Foo
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ApplicationUser Creator { get; set; }
}

Inside of my Foo controller in the edit action I want to check that the User requesting the edit is the Creator.

//ApplicationDbContext inherits IdentityDbContext
private ApplicationDbContext appDb { get; set; }
...
public async Task<ActionResult> Edit(int? id)
{
        Foo target =  appDb.Foos.First(o => o.Id == id);

        if (target == null)
        {
            return HttpNotFound();
        }

        if (target.Creator.Id != User.Identity.GetUserId())
        {
            ViewBag.Error = "Permission denied.";
            return Redirect(Request.UrlReferrer.ToString());
        }

        return View(target);
    }

The problem is that for some reason target.Creator returns null, although all Foo have a Creator object referenced. In the same controller, in the details action it gets pulled just fine:

var entry = appDb.Foos.Where(f=>f.Id == id)
            .Select(foo => new FooViewModel()
            {
                Id = foo.Id,
                Title = foo.Title,
                CreatorId = foo.Creator.Id,
                CreatorName = foo.Creator.FirstName,
            }).FirstOrDefaultAsync();

What am I missing? What is so different about trying to access foo.Creator inside of the Display query than trying to access it directly on a Foo object? I thought EF would have queried for foo.Creator when I requested the Foo itself.

Should I change foo.Creator to store foo.CreatorId instead?

Thanks.

like image 387
user3352250 Avatar asked Dec 22 '25 13:12

user3352250


1 Answers

The navigation properties are not feched by default. If you need them, eager load them using .Include():

Foo target =  appDb.Foos.First(o => o.Id == id).Include(f => f.Creator);

Your code will not work at all: if you try to find the first element, with .First() and it doesn't exist, you'll get an exception. I.e, your code will never hit if (target == null).

You should use .FirstOrDefault(), or better thant that, Find().

like image 114
JotaBe Avatar answered Dec 24 '25 05:12

JotaBe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!