问题
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
回答1:
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
回答2:
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:
- Convert it to something that implements
IList
, e.g. calldbPerson.ToList()
. - If you really need just the first element, use the
IQueryable
extension method for that purpose:dbPerson.First()
- If you want an arbitrary element as
[x]
, use theIQueryable
extension method for that purpose:dbPerson.Skip(x).First()
回答3:
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--;
回答4:
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;
}
来源:https://stackoverflow.com/questions/13879416/cannot-apply-indexing-with-to-an-expression