无法将类型’System.Linq.IQueryable’隐式转换为’System.Data.Entity.DbSet’
我是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 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); }
我只是想知道为什么另一个有效,但另一个没有。
一个很好的例子可能有帮助。 谢谢
第一个场景不起作用的原因是System.Linq.IQueryable
是一个由System.Data.Entity.DbSet
类实现的接口。 在C#中,如果类C
实现接口I
,那么当涉及类型之间的转换时,您也可以将I
视为C
的基类(即使是语义class C : I
建议使用这种方法)。 并且由于您不能隐式地(即不详细地)将类(或接口)强制转换为其后代类之一,因此在尝试执行此操作时会出现编译时错误。 你可以做相反的事情,即将后代类隐式地转换为它的基类(或接口)。 这正是第二种情况中发生的情况。
在您的情况下,您可以通过显式转换欺骗编译器:
query = (DbSet) query.Where(p => p.Id == id);
但我强烈建议你不要因为你最终得到一个混乱的exception,因为query.Where(p => p.Id == id)
的结果实际上不是DbSet
的实例,但是而是一些表示在DbSet
上执行的查询结果的类,它实现了IQueryable
接口。
总而言之,让我们来看看所有场景:
场景1:
//query is of type DbSet var query = _db.Products; if (bool) { //here you're trying to assign a value of type IQueryable //to a variable of it's descendant type DbSet //hence the compile-time error query = query.Where(p => p.Id == id); }
场景2:
//here you implicitly cast value of type DbSet //to IQueryable , which is OK IQueryable query = _db.Products; if (bool) { //here you're assigning a value of type IQueryable //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, because you perform //a query on the DbSet var query = from product in products select product; if (bool) { //here you're assigning a value of type IQueryable //to a variable of the same type, which is OK query = query.Where(p => p.Id == id); }
使用var
,编译器会推断赋值右侧的表达式类型。 当你写作
var query = _db.Products;
query
的类型为DbSet
,并且不能为其分配任何IQueryable
, Where
扩展方法返回。
当您使用查询语法时, query
又是IQueryable
,这使它工作。 这相当于写作
var query = products.Select(t => t);
Select
扩展方法(如Where
)返回IQueryable
。
这是因为_db.Products
不是查询,而是DbSet。
第二个块可以工作,因为你将它转换为IQueryable,最后一个块可以工作,因为它是一个实际的查询。
var query = _db.Products.Where(x => true); if (bool) { query = query.Where(p => p.Id == id); }