【问题标题】:Efficiently check if record exists in database using Entity framework LINQ使用实体框架 LINQ 有效检查数据库中是否存在记录
【发布时间】:2018-01-29 14:49:00
【问题描述】:

我需要使用实体框架检查客户代码是否已经存在于数据库中。理想情况下,我会像这样编写普通的 sql 查询:

select id from dbo.Customer where RecActive = 1 and Code = 'xxx';

如果查询结果为空,则表示代码'xxx'的客户还不存在。在实体框架中,有多种编写方式,但我正在寻找上面最接近的一种注意:代码字段上有唯一索引

  using (var context = new CustomerContext())
  {
    // not very efficient as it reads all columns
    return context.Customers.Where(c => c.RecActive && c.Code == customerCode).SingleOrDefault() != null ? true : false;

    return context.Customers.Where(c => c.RecActive && c.Code == customerCode).Count() > 0 ? true : false;

    // translates to this query:
    // exec sp_executesql N'SELECT [Limit1].[Id] AS [Id]
    // FROM ( SELECT TOP (2) 
    //        [Extent1].[Id] AS [Id]
    //        FROM [dbo].[Customer] AS [Extent1]
    //        WHERE ([Extent1].[RecActive] = 1) AND (([Extent1].[Code] = 
    //          @p__linq__0) OR (([Extent1].[Code] IS NULL) AND 
    //          (@p__linq__0 IS NULL)))
    //        )  AS [Limit1]',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'xxx'
    int a = context.Customers.Where(c => c.RecActive && c.Code == customerCode).Select(c => c.Id).SingleOrDefault();             
    return a > 0 ? true : false;

    return context.Customers.Where(c => c.RecActive && c.Code == customerCode).Any();
  }

也许还有其他好的(性能替代)?注意:我必须使用实体框架 linq 而不是原始查询(我真的很喜欢),因为 linq 在整个项目中一直使用。

【问题讨论】:

  • return context.Customers.Where(c => c.RecActive && c.Code == customerCode).Any();
  • 为什么你需要这样的东西?您是否正在尝试编写 UPSERT 方法?如果Code 是主键,EF 将在插入或更新之前自行执行检查。如果您出于其他原因想要检查是否存在,请使用Any()。如果您想要 ID,请使用 .Where()...).Select(c=>c.id)
  • 为什么<condition> ? true : false - 对我来说似乎是多余的。
  • Any() 可能会在其查询中使用select null,而不是select id。这是一个非常小的区别,但问题在于既要询问它是否与原始查询的轻微低效率相匹配,又要询问它是性能最高的。

标签: c# entity-framework linq linq-to-sql


【解决方案1】:

如果您只想检查是否存在,请使用.Any()。如果要检索符合条件的 ID,请使用 Select,例如:

 context.Customers
        .Where(c => c.RecActive && c.Code == customerCode)
        .Select(c => c.id);

如果多个 ID 是有效结果,则无论id 的类型是什么,您的方法都应返回一个字符串/整数数组。你可以返回一个带有.ToArray();的ID数组

 return context.Customers
               .Where(c => c.RecActive && c.Code == customerCode)
               .Select(c => c.id)
               .ToArray();

如果您期望有多个 ID,则您必须决定在获得多个结果时该怎么做:

  • 如果有多个结果,FirstOrDefault() 将返回第一个 ID 而不会抛出。
  • 如果有多个结果阻止使用可能无效的 ID,SingleOrDefault() 将抛出。

例如:

return context.Customers.Where(c => c.RecActive && c.Code == customerCode)
               .Select(c => c.id)
               .SingleOrDefault();

【讨论】:

    【解决方案2】:

    由于您的代码忽略了实际 ID,并且只返回一个 true/false 指示其存在,您可以通过一次调用 Any 来完成:

    return context.Customers.Any(c => c.RecActive && c.Code == customerCode);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-27
      相关资源
      最近更新 更多