无法将类型’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 ,并且不能为其分配任何IQueryableWhere扩展方法返回。

当您使用查询语法时, 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); }