首页 > 解决方案 > 查询列表中的单个项目

问题描述

问题

我想在我的详细信息页面上显示一只宠物。我无法理解如何编写 LINQ(Method Syntax) 从数据库中提取单个宠物/物品。

到目前为止我的理解

使用 LINQ 时,它的闪亮目的是能够遍历IEnumerable数据库中的数组或列表。当您查看我HomeController的 .

要求

使用方法语法,我应该使用什么查询来拉单个宠物?

家庭控制器.cs

[HttpGet("pet/{PetId}")]
public IActionResult Detail(Pet singlePet)
{
        List<Pet> Animal = _context.Pets
        //***MISSING QUERY CODE HERE***

        return View("Pet", singlePet);
}

详细信息.cshtml

@model PetViewModel

<div>
    <h1>Pet Shelter</h1>
    @foreach (Pet creature in Model.Pets)
    {
        <h3>Details about: @creature.Name</h3>
        <div>
            <p>Pet Type: @creature.Type</p>
            <p>Description: @creature.Description</p>
            <p>Skill One:@creature.Skill1</p>
            <p>Skill Two:@creature.Skill2</p>
            <p>Skill Three:@creature.Skill3</p>
        </div>
    }
</div>

PetViewModel.cs

using System.Collections.Generic;

namespace petShelter.Models
{
    public class PetViewModel
    {
        public Pet Animal { get; set; }
        public List<Pet> Pets { get; set; }
        public List<Owner> Owners { get; set; }
        public Owner Owner { get; set; }
    }
}

宠物.cs

using System;
using System.ComponentModel.DataAnnotations;

namespace petShelter.Models
{
    public class Pet
    {
        [Key]
        public int PetId { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Type { get; set; }

        [Required]
        public string Description { get; set; }

        public string Skill1 { get; set; }
        public string Skill2 { get; set; }
        public string Skill3 { get; set; }


        public DateTime CreatedAt { get; set; }
        public DateTime UpdatedAt { get; set; }

        public Owner Owner { get; set; }
        public int? OwnerId { get; set; }

    }
}

标签: c#asp.net-mvcentity-frameworklinqlinq-method-syntax

解决方案


精简版

利用

var singlePet=_context.Pets.Find(someId);

或者

var singlePet=_context.Pets.FirstOrDefault(x=>x.PetId=someId);

解释

LINQ 查询不查询列表。它们由 LINQ 提供程序转换为目标数据存储可以理解的任何内容。查询数据库时,它们被转换为 SQL。

List<Pet> Animal = _context.Pets不会编译,这是一件非常好的事情——如果编译了,它会将整个表加载到内存中而不是查询它。过滤将在客户端执行,没有索引的好处。由于浪费了 IO、浪费了 RAM,甚至更糟糕的是,当只需要一个行时,对表中的每一行都进行了锁定,因此性能将比简单的 SQL 查询差几个数量级。过多的锁将导致尝试使用同一张表的所有其他请求延迟。

Pets是一个DbSet<T>,不是一个List<T>。它不是一个容器,它代表一个实体,本身不包含任何数据。它可用于编写转换为 SQL 的查询。

假设PetId是主键Pet,加载单个记录的最简单和最快的方法是调用DbSet.Find。此方法使用提供的主键值检索对象。

这个查询:

var singlePet=_context.Pets.Find(someId);

翻译成

select ... 
from Pets 
where PetID=@id

这将在 DbContext 中加载和缓存Pet 实例。之后,每次Find在同一个请求中调用相同的PK值,都会返回缓存的对象。

查询

var singlePet=_context.Pets.FirstOrDefault(x=>x.PetId=someId);

将翻译为

select top 1 ... 
from Pets 
where PetID=@id

在这种情况下没有缓存任何内容。


推荐阅读