我是Linq
中的新人,因此下面有这些情况。
编译过程中出现以下错误,Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Entity.DbSet'.
var query = _db.Products;
if (bool) {
query = query.Where(p => p.Id == id);
}
所以我尝试将var
更改为IQueryable
,然后就可以了。
IQueryable<Product> query = _db.Products;
if (bool) {
query = query.Where(p => p.Id == id);
}
然而,我试图再次改变它(见下文)并且它有效。
var query = from product in products
select product;
if (bool) {
query = query.Where(p => p.Id == id);
}
我只是想知道为什么另一个有效,但另一个没有。
对示例的一个很好的解释可能有所帮助。感谢
答案 0 :(得分:26)
第一种情况不起作用的原因是System.Linq.IQueryable
是一个由System.Data.Entity.DbSet
类实现的接口。在C#中,如果类C
实现了接口I
,那么当谈到类型之间的转换时,您也可以将I
视为C
的基类(甚至是语义) class C : I
提出了这样一种方法)。并且由于您不能隐式地(即不是冗长地)将类(或接口)强制转换为其后代类之一,因此在尝试执行此操作时会出现编译时错误。你可以做相反的事情,即将后代类隐式地转换为它的基类(或接口)。这正是第二种情况中发生的情况。
在您的情况下,您可以通过显式转换来欺骗编译器:
query = (DbSet<Customer>) query.Where(p => p.Id == id);
但我强烈建议你不要因为你最终会遇到一个混乱的异常,因为query.Where(p => p.Id == id)
的结果实际上并不是DbSet<Customer>
的一个实例,而是一些表示在DbSet<Customer>
上执行查询的结果的类,它实现了IQueryable
接口。
总而言之,让我们来看看所有场景:
情景1:
//query is of type DbSet<Customer>
var query = _db.Products;
if (bool) {
//here you're trying to assign a value of type IQueryable<Customer>
//to a variable of it's descendant type DbSet<Customer>
//hence the compile-time error
query = query.Where(p => p.Id == id);
}
情景2:
//here you implicitly cast value of type DbSet<Customer>
//to IQueryable<Customer>, which is OK
IQueryable<Customer> query = _db.Products;
if (bool) {
//here you're assigning a value of type IQueryable<Customer>
//to a variable of the same type, which is also OK
query = query.Where(p => p.Id == id);
}
情景3:
//I assume you have the following line in your code
var products = _db.Products;
//query is of type IQueryable<Customer>, because you perform
//a query on the DbSet<Product>
var query = from product in products
select product;
if (bool) {
//here you're assigning a value of type IQueryable<Customer>
//to a variable of the same type, which is OK
query = query.Where(p => p.Id == id);
}
答案 1 :(得分:8)
使用var
时,编译器会在赋值右侧推断出表达式的类型。当你写
var query = _db.Products;
query
属于DbSet<Product>
类型,无法分配任何IQueryable<Product>
Where
扩展方法返回的内容。
当您使用查询语法时,query
再次成为IQueryable<Product>
,这使其有效。这相当于写作
var query = products.Select(t => t);
Select
扩展方法,如Where
,返回IQueryable<Product>
。
答案 2 :(得分:0)
这是因为_db.Products
不是查询,而是DbSet。
第二个块可以工作,因为你将它转换为IQueryable,最后一个块可以工作,因为它是一个实际的查询。
答案 3 :(得分:0)
var query = _db.Products.Where(x => true);
if (bool) {
query = query.Where(p => p.Id == id);
}