Reputation: 3945
var dbPerson = from p in db.People
where p.Id == PersonId select p;
dbPerson[0].HolidaysRemaining--;
is throwing me an error with dbPerson[0] saying cannot apply indexing with [] to an expression of type 'system.linq.lqueryable,holidayBookingApp.model.person>
can someone please advise how I can resolve this?
Thanks
Upvotes: 3
Views: 13644
Reputation: 2541
You should understand the idea behind the Linq & IEnumerable (& IQueryable) interface. IEnumerable used for lazy loading of sequences, so if you create an extension method for loop like this:
public static IEnumerable<T> LazyForEach<T>(this IEnumerable<T> source, Action<T> action) //action to perform
{
if (action == null) throw new ArgumentNullException("action");
foreach (T element in source)
{
action(element);
yield return element;
}
}
and try to use LazyForEach in IEnumerable-returning method (Linq) chain:
db.People.Where(p=>p...).LazyForEach(p=>
{
MessageBox.Show(p.ToString());
});
your code in provided action will not execute until you force enumeration (maybe partial) with ToList/ToArray/ElementAt/First/Last/Any/Take/Skip ... or you can create alt. extension:
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null)
return null;
if (action == null) throw new ArgumentNullException("action");
//var sourceList = source.ToList(); //forcing enumeration
var sourceList = new List<T>();
foreach (var element in source)
{
action(element);
sourceList.Add(element);
}
return sourceList;
}
Upvotes: 1
Reputation: 28338
The result of your LINQ query is not a List
, it's a custom type of IQueryable
that does not have an indexer. You cannot get random access to the results of a LINQ query in that form.
You have multiple options if you really need that:
IList
, e.g. call dbPerson.ToList()
. IQueryable
extension method for that purpose: dbPerson.First()
[x]
, use the IQueryable
extension method for that purpose: dbPerson.Skip(x).First()
Upvotes: 5
Reputation: 650
It's because dbPerson
is IEnumerable, what doesn't support indexing concept. You can use some Linq methods, like dbPerson.First()
, or simply convert it to List:
var list = dbPerson.ToList();
list[0].HolidaysRemaining--;
Upvotes: 2
Reputation: 50104
To get the first item that your query dbPerson
returns, use
var firstPerson = dbPerson.First();
or Single
if you only expect one match and want an exception to be thrown if this expectation is broken.
However, I'm not convinced firstPerson.HolidaysRemaining--;
will change anything in your database without further code:
var dbPeopleWithThisId = from p in db.People
where p.Id == PersonId
select p;
var specificPerson = dbPeopleWithThisId.Single();
specificPerson.HolidaysRemaining--;
db.SaveChanges(); // Thanks to J. Steen
Upvotes: 4