不能将带有[]的索引应用于表达式

时间:2012-12-14 13:15:43

标签: c# indexing expression

 var dbPerson = from p in db.People 
                where p.Id == PersonId select p;
 dbPerson[0].HolidaysRemaining--;

给我一​​个错误,dbPerson [0]说不能将带有[]的索引应用于类型为'system.linq.lqueryable,holidayBookingApp.model.person>

的表达式

有人可以告诉我如何解决这个问题吗?

由于

4 个答案:

答案 0 :(得分:5)

您的LINQ查询的结果不是List,它是一个没有索引器的自定义类型IQueryable。您无法随机访问该表单中的LINQ查询结果。

如果你真的需要,你有多种选择:

  • 将其转换为实现IList的内容,例如致电dbPerson.ToList()
  • 如果您确实只需要第一个元素,请使用IQueryable扩展方法实现此目的:dbPerson.First()
  • 如果您想将任意元素设为[x],请使用IQueryable扩展方法实现此目的:dbPerson.Skip(x).First()

答案 1 :(得分:4)

要获取查询dbPerson返回的第一个项目,请使用

var firstPerson = dbPerson.First();

Single如果您只期望一次匹配,并希望在此期望被破坏时抛出异常。

但是,我不相信firstPerson.HolidaysRemaining--;会在没有其他代码的情况下更改数据库中的任何内容:

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 :(得分:2)

这是因为dbPerson是IEnumerable,它不支持索引概念。您可以使用一些Linq方法,例如dbPerson.First(),或者只是将其转换为List:

var list = dbPerson.ToList();
list[0].HolidaysRemaining--;

答案 3 :(得分:1)

你应该理解Linq& amp; IEnumerable(& IQueryable)接口。 IEnumerable用于延迟加载序列,所以如果你为这个循环创建一个扩展方法:

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;
            }
        }

并尝试在IEnumerable-returning方法(Linq)链中使用LazyForEach:

db.People.Where(p=>p...).LazyForEach(p=>
{
   MessageBox.Show(p.ToString());
});

在您使用ToList / ToArray / ElementAt / First / Last / Any / Take / Skip强制枚举(可能是部分)之前,您提供的操作中的代码将不会执行...或者您可以创建alt。扩展:

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;
        }