如何根据多个条件使用Linq查找特定项目?

时间:2018-12-27 15:04:24

标签: c# asp.net-mvc linq asp.net-identity

我有一个非常简单的查询:

//user from UserManager from default AccountController from .net Identity
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

var product = await Task.Run(() 
    => db.WatchedProducts.Where(u => u.ApplicationUserId == user.Id && u.ProductId == id));

我想做的是在product列表中找到特定的WatchedProducts。它的模型如下所示:

public class WatchedProduct
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("ApplicationUser")]
    public string ApplicationUserId { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }

    [ForeignKey("Product")]
    public int ProductId { get; set; }
    public virtual Product Product { get; set; }
}

ApplicationUser的列表为WatchedProducts

我的问题是,为什么我得到WatchedProduct product而不是得到IQueryable<WatchedProduct> product

3 个答案:

答案 0 :(得分:2)

发生这种情况是因为您正在使用方法Where()Where()方法会根据lambda表达式=> u.ApplicationUserId == user.Id && u.ProductId == id过滤数据,并返回IQueryable<TSource>IEnumerable<TSource>(请参阅Reza Aghaei的详尽解释)。

如果您想获得WaterProduct产品,只需通过FirstOrDefault()方法获得它:

var product = await Task.Run(() 
    => db.WatchedProducts.Where(u => u.ApplicationUserId == user.Id && u.ProductId == id)
       .FirstOrDefault());

您没有获得任何数据,因为您没有实现查询。这称为延迟执行。延迟执行意味着直到需要必要的数据,您的linq代码才会在数据库中执行。因此,要具体化数据或在数据库中执行查询,您应该调用以下方法:

foreach, toList(), First(), FirstOrDefault(), Single(), SingleOrDefault(), etc...

答案 1 :(得分:2)

这是因为let arr = { "0": { "id": 0, "country": "usa", "sum": 201, }, "1": { "id": 1, "country": "fr", "sum": 133, } } const reducer = (accumulator, currentValue) => accumulator.sum + currentValue.sum; let sum = Object.values(arr).reduce(reducer); console.log(sum)扩展方法返回了Where。如果设置了数据库,它将返回IEnumerable<TSource>的{​​{1}}。

在您的情况下,由于您使用的是异步/等待模式,因此您可以使用IQueryable<TSource>来获得单个项目:

IEnumerable<TSource>

答案 2 :(得分:1)

您应该使用SingleOrDefault

据我所知,由于您使用的产品ID是唯一的,因此结果应该是唯一的

var product = await Task.Run(() 
    => db.SingleOrDefault(u => u.ApplicationUserId == user.Id && u.ProductId == id));

这将返回一项;如果未找到,则返回null。注意,如果找到一个以上的项目,它将引发异常,这不应该,因为产品ID很可能是唯一的,并且如果找到更多的项目,您将知道您搞砸了数据库中有多个产品相同的ID

如果该查询可以有一个以上的记录作为结果,那么请使用 FirstOrDefault而不是SingleOrDefault,但是逻辑并不十分正确,因为让查询返回一个或一个都不返回到列表中的第一个查询是没有意义的。