尝试获取集合中的第一个项目返回NULL

时间:2012-03-01 21:30:20

标签: c# linq linq-to-sql

我以前使用Stored Procs进行了大量的开发来进行所有数据修改。

但我现在需要使用LINQ To SQL,而基本的基本任务让我难以理解。

我有一个名为Book(Title,Author等)的课程。实例化并添加了许多书籍 public ObservableCollection Books

到目前为止,我可以看到它的藏品中有有效的书籍。

我有一个函数 DeleteOldestBook(),它只是获取书籍中的第一本书,并删除。这是我遇到麻烦的地方。

我尝试选择

Book BookToDelete = Books.Take(1) as Book;

但它总是返回NULL。

我做了一个hacky解决方法:

var AllBooks = from BookToDelete in Books select BookToDelete;
foreach (Book BookToDelete in AllBooks)
{ 
    //  BookToDelete.dostuff takes place ... 
    break; // only do 1
}

但这太糟糕了,我知道我错过了一些简单的东西。

LINQ专家的任何想法?如果您需要更多代码,请告诉我。

提前致谢

6 个答案:

答案 0 :(得分:10)

Take()会返回IEnumerable<Book>。因此,您将其转换为Book的尝试失败,返回空值。

改为使用Books.First()Books.FirstOrDefault()

对Nitpickers的澄清:如果Take()直接来自IQuerable<Book>,则Books实际上可能会返回DataContext

答案 1 :(得分:6)

Take将返回一个包含n个元素的集合。您仍然需要迭代该集合。在您的情况下,集合大小为1。

First将返回集合中的第一项。

额外信用

如果您的收藏品尚未排序,请使用OrderBy

Book bookToDelete = Books.OrderBy(b => b.SomeDate).First();

答案 2 :(得分:6)

只需使用FirstOrDefault()

var firstBook = Books.FirstOrDefault();

如果集合中没有图书,firstBook将为null,否则将设置为第一项。

通常情况下你会希望通过一些标准获得第一本书,如果是这样的话,请事先使用适当的Where子句:

var firstThriller = Books.Where(b => b.Type == "Thriller")
                         .FirstOrDefault();

答案 3 :(得分:3)

我会用

Books.First();

而不是

Take(1);

Take Extension方法会返回IQueryable<T>,您尝试转换为TBook)。这就是你总是得到null的原因。

答案 4 :(得分:2)

是的,您错过了First()扩展程序:

Book BookToDelete = Books.First();

请注意,Take(int)会返回一系列图书(IQueryable<T>) - 即使该序列仅包含您的案例中的一个项目。由于没有IQueryable<T>T的转换,as将返回null。

答案 5 :(得分:1)

Take会返回包含单个元素的IEnumerable<T>,您想要的是:

Books.FirstOrDefault();

返回第一个元素(如果null为空,则返回Books。)