无法将类型'System.Linq.IQueryable'隐式转换为'System.Data.Entity.DbSet'

Boy*_*smo 23 c# linq

我是新手,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);
}
Run Code Online (Sandbox Code Playgroud)

所以,我试图改变varIQueryable和它的作品.

IQueryable<Product> query = _db.Products;
if (bool) {
  query = query.Where(p => p.Id == id);
}
Run Code Online (Sandbox Code Playgroud)

但后来,我试图再次改变它(见下文)并且它有效.

var query = from product in products
            select product;
if (bool) {
  query = query.Where(p => p.Id == id);
}
Run Code Online (Sandbox Code Playgroud)

我只是想知道为什么另一个有效,但另一个没有.

一个很好的例子可能有帮助.谢谢

Grx*_*x70 29

第一种情况不起作用的原因System.Linq.IQueryableSystem.Data.Entity.DbSet该类是由类实现的接口.在C#中,如果类C实现了接口I,那么当涉及到类型之间的转换时,您也可以将其I视为C基类(即使语义也class C : I提出了这样的方法).并且由于您不能隐式地(即不是冗长地)将类(或接口)强制转换为其后代类之一,因此在尝试执行此操作时会出现编译时错误.你可以做相反的事情,即将后代类隐式地转换为它的基类(或接口).这正是第二种情况中发生的情况.

在您的情况下,您可以通过显式转换欺骗编译器:

query = (DbSet<Customer>) query.Where(p => p.Id == id);
Run Code Online (Sandbox Code Playgroud)

但我强烈建议你不要因为你最终会得到一个混乱的异常,因为结果query.Where(p => p.Id == id)实际上不是一个实例DbSet<Customer>,而是一些代表在a上执行查询的结果的类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); 
}
Run Code Online (Sandbox Code Playgroud)

场景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); 
}
Run Code Online (Sandbox Code Playgroud)

场景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); 
}
Run Code Online (Sandbox Code Playgroud)


Eli*_*bel 9

使用var编译器时,可以在赋值右侧推断表达式的类型.当你写作

var query = _db.Products;
Run Code Online (Sandbox Code Playgroud)

query是类型的DbSet<Product>,它可以不被分配任何IQueryable<Product>,其中Where扩展方法的回报.

当您使用查询语法时,query再次IQueryable<Product>使用它.这相当于写作

var query = products.Select(t => t);
Run Code Online (Sandbox Code Playgroud)

Select扩展方法一样Where,返回IQueryable<Product>.