微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

查询列表中的单个项目

如何解决查询列表中的单个项目

问题

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

我目前的理解

在使用 LINQ 时,它的闪亮目的是能够遍历数据库中的 IEnumerable 数组或列表。当您查看我的 HomeController 时,我非常有信心我有正确的代码段来构建我想要的 MINUS 查询

请求

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

HomeController.cs

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

        return View("Pet",singlePet);
}

Details.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; }
    }
}

Pet.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; }

    }
}

解决方法

短版

使用

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 查询差数量级,更糟糕的是,在只需要一个表时就锁定表中的每一行。过多的锁会导致其他尝试使用同一张表的请求出现延迟。

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

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

这个查询:

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

翻译为

select ... 
from Pets 
where PetID=@id

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

查询

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

将翻译成

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

在这种情况下没有缓存任何东西。

,

如果你不关心,只想从数据库中得到一个结果,你可以做这样的事情

var singlePet = _context.Pets.First();

如果你想要第一个匹配表达式的结果,你可以这样做

var singlePet = _context.Pets.First( e => e.Id == '1');

如果你只期待一个与表达式匹配的结果,你可以做这样的事情

var singlePet = _context.Pets.Single( e => e.PetId == '1' );
,

如果你只想要一个,根本没有过滤器,你可以使用它,它会让你成为列表中的第一个:

var aSpecificPet = Pets.FirstOrDefault();

如果您需要指定某种条件来确定要携带哪种宠物,您可以使用以下内容:

var aMoreSpecificPet = Pets.FirstOrDefault(x=>x.Type == "Dog");

请记住,您作为条件传递的任何内容都将过滤宠物列表,而使用 FirstOrDefault,您将获得第一个(如果有)符合您的条件的宠物。

此外,默认值通常为空(以防没有宠物符合您的条件),因此最好始终添加像

这样的行
if(pet != null){
  your code
}

如果您想要所有符合该条件的宠物,请使用:

var allDogsInPets = Pets.Where(x=>x.Type == "Dog").ToList();

.ToList() 返回一个包含符合您条件的宠物的新列表。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。