The first and most obvious improvement would be better variable naming:
IQueryable<Article> privateArticlesCreatedByUser =
db.Articles.Include(article => article.Categories)
.Include(article => article.Shared)
.Where(article => article.Private && article.createdby == User.Identity.Name);
IQueryable<Article> articlesSharedWithUser =
db.Articles.Include(article => article.Shared)
.Where(sharedArticle => sharedArticle.Shared.Any(shareRecipient => shareRecipient.User == user));
IQueryable<Article> articlesCreatedByOrSharedWithUser = privateArticlesCreatedByUser.Concat(articlesSharedWithUser);
IQueryable<Category> categories = db.Categories
.Where(category => articlesCreatedByOrSharedWithUser.Any(articleCategory => articleCategory.categoryID == category.Id));
Obviously these names may not perfectly align with what the data means (as they're basically educated guesses on my part), but already they're a lot easier for somebody else to understand.
I also changed your &
to an &&
, since it then saves an equality check sometimes.
I also notice that you are including shared articles occurs twice. This might be too trivial an improvement and it's debatable if it will improve readability at all, but you could try this:
var sharedArticles = db.Articles.Include(article => article.Shared);
IQueryable<Article> privateArticlesCreatedByUser =
sharedArticles.Include(article => article.Categories)
.Where(article => article.Private && article.createdby == User.Identity.Name);
IQueryable<Article> articlesSharedWithUser = sharedArticles
.Where(sharedArticle => sharedArticle.Shared.Any(shareRecipient => shareRecipient.User == user));
IQueryable<Article> articlesCreatedByOrSharedWithUser = privateArticlesCreatedByUser.Concat(articlesSharedWithUser);
IQueryable<Category> categories = db.Categories
.Where(category => articlesCreatedByOrSharedWithUser.Any(articleCategory => articleCategory.categoryID == category.Id));