Reputation: 5705
Below is a an anonymous object, assuming that Course
object can have no related Progress
object, so to avoid having Progress
return an empty array, I am trying to make it return an object with values equal to zeroes:
var courses = await _context.courses
.Include(c => c.Progress)
.ToListAsync();
var myCourses = courses
.Select(c => new
{
Title = c.Title,
Progress = (c.Progress.ToList().Select(x => new { x.CurrentChapter, x.Completed }) != null)
? (c.Progress.ToList().Select(x => new { x.CurrentChapter, x.Completed }))
: (new List<Dictionary<string, int>> { { "CurrentChapter", 0 }, { "Completed", 0 } })
})
.ToList();
return Ok(myCourses);
But I am getting an error in the last part of the ternary as follows:
No overload for method 'Add' takes 2 arguments
Upvotes: 0
Views: 453
Reputation: 5705
Discussion with @Flydog57 helped me dissipate some confusion since this is the first time I make a ternary inside an anonymous object, and after made some edits to my question to make it short and concise, and some research, I could finally solve the issue, here is what I ended up to:
var myCourses = courses
.Select(c => new
{
Title = c.Title,
Progress = (c.Progress.Any())
? (c.Progress.ToList().Select(x => new { x.CurrentChapter, x.Completed }))
: (new[] { new {CurrentChapter = 0, Completed = 0} }.ToList())
})
.ToList();
So using Dictionary in the last part was not the correct way, and also the first part was not relevant, so now instead of returning:
{
"title": "Course having child Progress objects",
"progress": [
{
"currentChapter": 2,
"completed": 0
},
{
"currentChapter": 0,
"completed": 0
}
]
},
{
"title": "Course having NO child Progress objects",
"progress": []
}
it is returning:
{
"title": "Course having child Progress objects",
"progress": [
{
"currentChapter": 2,
"completed": 0
},
{
"currentChapter": 0,
"completed": 0
}
]
},
{
"title": "Course having NO child Progress objects",
"progress": [
{
"currentChapter": 0,
"completed": 0
}
]
}
Upvotes: 0
Reputation: 7111
Your code as you show it is not very salvageable (nor is it anywhere near readable). I took your code, removed the superfluous ToList
calls and added a bit more to get it to nearly compile:
As I mentioned in the comments, the ToList
calls are superfluous - course.Progress
must be enumerable, all ToList
does is create a new list that copies the information in course.Progress
My added code:
var course = new {Progress = new List<Progress>() };
That allows the course.Progress.Select
call to make a little sense. If course
isn't an instance of a type that has a property named Progress
that implements IEnumerable<Progress
, well, I'm not sure how to start this.
Then, the beginning of your code, reformatted starts making sense (it trails off at the end).
Here's your code, without .ToList
and reformatted:
var progress = (course.Progress
.Select(x => new { x.CurrentChapter, x.Completed }) != null)
? (course.Progress.Select(x => new { x.CurrentChapter, x.Completed }))
: (new List<Dictionary<string, int>{ { "CurrentChapter", 0 }, { "Completed", 0 } });
As I mentioned in the comments, IEnumerable<T>.Select
never returns null
, so the initial null check is useless. I'm guessing that you are trying to check that the progress collection is empty.
Also note that when you use a ternary, both possible choices must be the same type. In one case, you have an anonymous type, in the other, you have a Dictionary. That's never going to compile.
Like the other commenters, I think you are better off using an if/else
. However, since you seem to want to get get an anonymously typed thing called Progress
. I don't have a clue how you declared that, so I worked around it with a tuple. I think this is kinda-sorta what you are trying to do:
(int currentChapter, int completed) progressTuple;
if(!course.Progress.Any())
{
progressTuple = (0, 0);
}
else
{
var firstProgress = course.Progress.First();
progressTuple = (firstProgress.CurrentChapter, firstProgress.Completed);
}
var progress = new { CurrentChapter = progressTuple.currentChapter, Completed = progressTuple.completed };
Now, progress
is an anonymous type like you seem to want. Note that I picked the first item out of your collection. I don't really know what you wanted to do there.
Since you have a type named Progress
that has the properties you wanted, this would make more sense:
Progress progress;
if (!course.Progress.Any())
{
progress = new Progress { CurrentChapter = 0, Completed = 0 };
}
else
{
progress = course.Progress.First();
}
Now that you have code that is simplified and that makes sense, you could try reintroducing a ternary operator if your tastes run towards the unreadable (I find complex ternaries at the edge of my code comprehension skills).
Upvotes: 1