简体   繁体   中英

Linq query causes null reference exception when accessing linked tables

So I have the following linq query for a test blog:

var random = new Random();
var random = context.Blog.OrderBy(x => random.Next())
                         .Where(x => x.DisplayStatus == "Approved")
                         .Select(x => new Blog 
                          { 
                              Title = x.Title,
                              Content = x.Content,
                              AuthorId = x.AuthorId,
                              Author = x.Authors.AuthorName //null pointer exception here
                          }).Take(5).ToList() 

The trouble is, it throws a null pointer exception when it hits 'x.Authors.AuthorName'. I cannot figure out why. I know the author is there because it works fine when I use linq expressions (from x in context.Blog...etc), and it works in LinqPad. I can't use the linq expression, though, because I don't know how to declare 'OrderBy(x => random.Next())' without using a lambda expression.

this is the version that works without the random

var working = (from x in context.Blog
                 //NO known code to select random
                 where x.DisplayStatus == "Approved"
                 select new Blog 
                 {
                    Title = x.Title,
                    Content = x.Content,
                    AuthorId = x.AuthorId,
                    Author = x.Authors.AuthorName //NO null pointer exception
                 }).Take(5).ToList() 

Blog is a POCO class with no database relations. Authors is a database entity class with AuthorName being a simple string. Any idea on what is going on here?

I am not allowed to add a comment, so I ask here. What type is Authors ? From the name I guess it could be some type of Collection .

What I often do if one Property might be null is to add a ? :

Author = x.Authors?.AuthorName

You can get random sort using Guid.NewGuid() :

var random = context.Blog.OrderBy(x => Guid.NewGuid())
                     .Where(x => x.DisplayStatus == "Approved")
                     .Select(x => new Blog 
                      { 
                          Title = x.Title,
                          Content = x.Content,
                          AuthorId = x.AuthorId,
                          Author = x.Authors.AuthorName
                      }).Take(5).ToList() 

Or SqlFunctions.Rand :

var random = context.Blog.OrderBy(x => SqlFunctions.Rand())
                     .Where(x => x.DisplayStatus == "Approved")
                     .Select(x => new Blog 
                      { 
                          Title = x.Title,
                          Content = x.Content,
                          AuthorId = x.AuthorId,
                          Author = x.Authors.AuthorName
                      }).Take(5).ToList() 

Change your query to this:

var working = (from x in context.Blog
                 where x.DisplayStaus == "Approved"
                 select new Blog 
                 {
                    Title = x.Title,
                    Content = x.Content,
                    AuthorId = x.AuthorId,
                    Author = x.Authors.AuthorName
                 })
                 .AsEnumerable().OrderBy(x => random.Next())
                 .Take(5).ToList();

Edit:

I wasn't 100% sure what the error is and wanted to wait for the OP to check if my answer actually does what I believe it does.

I assumed that Entity Framework will not translate your query to SQL and therefor lose the ability to automatically load x.Authors , by moving the OrderBy the first "half" of the query, can be translated to SQL while the AsEnumerable().OrderBy() will run in memory.

So AsEnumerable() will force the query to be translated and exceuted in SQL, and the following OrderBy will run in memory.

Edit2:

About how to do it on the SQL Server and not loading the whole query to memory, I am afraid I can't help you with that, a google search brought this

Linq to Entities, random order

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM