RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 693150
Accepted
tretetex
tretetex
Asked:2020-07-17 17:09:10 +0000 UTC2020-07-17 17:09:10 +0000 UTC 2020-07-17 17:09:10 +0000 UTC

Find()、FirstOrDefault() 方法与 Entity Framework 一起使用时的区别

  • 772

如果需要通过主键从数据库中获取记录,可以使用这两种方法。如果条目存在于数据库中,这两种方法都将返回实体对象,否则它们将返回null。

它们有什么区别以及何时使用哪种方法?

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    tretetex
    2020-07-17T17:20:32Z2020-07-17T17:20:32Z

    要搜索和获取实体对象,可以使用以下方法:

    Find(),,,, . First()_ FirstOrDefault()_ Single()_SingleOrDefault()

    让我们考虑每一个:

    • 该方法Find()接受条目的主键作为参数。

      它的特殊之处在于,与其他方法不同,它首先访问内存并在 EntityFramework 跟踪的上下文对象中查找记录,然后才(如果没有找到)对数据库执行查询。如果上下文中有一个对象尚未存储在数据库中,该方法Find()仍将返回它(带有 state Added)。如果在那里或那里都找不到该条目,它将返回null。

      生成的 SQL 查询:

      SELECT TOP (2) 
      [Extent1].[Id] AS [Id], 
      [Extent1].[Title] AS [Title], 
      FROM [dbo].[Topics] AS [Extent1]
      WHERE [Extent1].[Id] = @p0
      

      值得注意的是,不是一条记录落入选择范围,而是两条SELECT TOP (2)。EF 在内部使用它来检查条目是否唯一。如果结果是多个具有相同主键的记录,EF 将抛出异常:

      System.InvalidOperationException:“序列包含多个元素”

    • 该方法FirstOrDefault()将谓词作为参数,这使得不仅可以通过主键进行搜索,还可以通过任何条件进行搜索。

      例如,让我们查找具有以下内容的条目Title == "test":

      var topic = context.Topics.FirstOrDefault(topic => topic.Title == "test");
      

      FirstOrDefault()不像Find()每次对数据库执行查询时,不管上下文中是否有数据。如果来自数据库的记录与上下文中的记录不同,EF 将从上下文中返回该记录。如果记录不在数据库中,null即使在上下文中也会返回。

      生成的 SQL 查询:

      SELECT TOP (1) 
      [Extent1].[Id] AS [Id], 
      [Extent1].[Title] AS [Title], 
      FROM [dbo].[Topics] AS [Extent1]
      WHERE [Extent1].[Id] = @p__linq__0
      

      在这里只查找一个条目SELECT TOP (1)。如果发现有几条记录,它将返回第一条。

    • 该方法First()类似FirstOrDefault(),但有一点不同 - 如果未找到该条目,将抛出异常:

      System.InvalidOperationException:“序列不包含任何元素”

    • 该方法SingleOrDefault()类似FirstOrDefault()并返回一个实体对象,或null. 但是,该请求会生成类似于以下内容的方法Find():

      SELECT TOP (2) 
      [Extent1].[Id] AS [Id], 
      [Extent1].[Title] AS [Title], 
      FROM [dbo].[Topics] AS [Extent1]
      WHERE [Extent1].[Id] = @p__linq__0
      

      如果找到多个条目,它会抛出异常:

      System.InvalidOperationException:“序列包含多个元素”

    • 方法Single()类似SingleOrDefault(),不同的是如果没有找到条目,会抛出异常:

      System.InvalidOperationException:“序列不包含任何元素”


    让我们总结一下:

    1. 什么时候使用Find()?

      当需要按主键查找,需要全选实体数据时。Find()如果记录已经加载到上下文中,则不会执行请求,因此在性能方面将优于所有其他方法。但是,如果您需要选择某些特定字段(例如,仅Id和Title),则必须使用其他方法。这同样适用于加载依赖数据(例如,通过Include())——Find()这是行不通的。

    2. 什么时候使用其他方法?

      如果您需要选择实体的某些字段或者您还需要加载依赖数据。使用哪些方法取决于个人需求:如果您需要检查条目是否存在(不抛出异常),以下方法是合适的*OrDefault():

      var topic = context.Topics
                         .Select(topic => new { topic.Id, topic.Title })
                         .FirstOrDefault(topic => topic.Id == 44);
      if (topic == null)
      {
          // ...
      }
      

      如果您希望上下文包含数据的本地副本,您可以从那里获取它而无需查询数据库。为此,您需要访问Local对象的属性DbSet:

      Var topic = context.Topics.Local.FirstOrDefault(topic => topic.Id == topicId)
               ?? context.Topics.FirstOrDefault(topic => topic.Id == topicId);
      

    使用的来源:

    • MSDN:实体框架查询和查找实体
    • 使用实体框架选择数据入门
    • StackOverflow:Find 和 Where().FirstOrDefault() 是否等效?
    • StackOverflow:在同一查询中使用 .Find() 和 .Include()
    • 25
  2. Yerik Zhartayev
    2020-02-06T21:28:57Z2020-02-06T21:28:57Z

    这不是对作者问题的回答,而是对用户 tretetex 先前回答的修正。关于

    它的特殊之处在于,与其他方法不同,它首先访问内存并在 EntityFramework 跟踪的上下文对象中查找记录,然后才(如果没有找到)对数据库执行查询。如果上下文中有一个对象尚未存储在数据库中,Find() 方法仍会返回它(具有已添加状态)。如果在那里或那里都找不到该条目,它将返回 null。

    FirstOrDefault()、Find()、First() 始终首先尝试在数据上下文缓存中查找对象,如果在缓存中找不到对象,则再在数据库中查找。(阅读俄语版 Joseph Albahari 和 Ben Albahari 书“C# 6 IN A NUTSHELL”第 384 页)这是我运行的测试

            using (var context1 = new DataContext())
            {
                //В данный момент у грузовика из context1 Title = "Грузовик"
                var truck1 = context1.Trucks.FirstOrDefault();
    
                using (var context = new DataContext())
                {
                    //У этого грузовика из context2 по прежнему Title = "Грузовик"
                    var truck2 = context.Trucks.FirstOrDefault();
    
                    truck1.Title = "Грузовик обновленный";
    
                    context1.SaveChanges();
    
                    //В данный момент у грузовика из context1 Title = "Грузовик 
                    //обновленный"
                    //этот цикл для задержки
                    for (int i = 0; i < 10000; i++)
                    {
                        var sum = Math.Sqrt(i);
                    }
    
                    //У этого грузовика из context2 по прежнему Title = "Грузовик", хотя в 
                    //БД уже имеет Title = "Грузовик"
                    var truck3 = context.Trucks.FirstOrDefault(t4 => t4.Id == truck2.Id);
                }
            }
    

    试验证实了这一点。

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5