【问题标题】:Link To Entities, how to fix Startswith resolving to sql CHARINDEX and ignoring index链接到实体,如何修复从解析到 sql CHARINDEX 并忽略索引开始
【发布时间】:2014-04-10 05:35:01
【问题描述】:

我有以下型号

public class Exchange
{
    public int Id { get; set; }

    [Index("ExchangeIdx", 1)]
    public int ExchangeSetId { get; set; }

    [Required]
    [MaxLength(10)]
    [Index("ExchangeIdx", 2)]
    public string BasePrefix { get; set; }

    [Required]
    [MaxLength(10)]
    [Index("ExchangeIdx", 3)]
    public string DestPrefix { get; set; }

}

我正在调用这个函数

var exchange = context.Exchanges.FirstOrDefault(x => 
   x.ExchangeSetId == exchangeSetId && 
   x.BasePrefix.StartsWith(baseNumber.Substring(4)) && 
   baseNumber.StartsWith(x.BasePrefix) &&
   destNumber.StartsWith(x.DestPrefix));

上面是试图重现下面的sql

SELECT TOP 1 * FROM Exchanges 
   where ExchangeSetId = 1 
   and BasePrefix like left('0732055827', 4) + '%' 
   and '0732055827' like BasePrefix +'%' 
   and '0732612680' like DestPrefix +'%'

但是它会产生以下令人讨厌的工作:

exec sp_executesql N'SELECT TOP (1) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[ExchangeSetId] AS [ExchangeSetId], 
    [Extent1].[BasePrefix] AS [BasePrefix], 
    [Extent1].[DestPrefix] AS [DestPrefix]
    FROM [dbo].[Exchanges] AS [Extent1]
    WHERE ([Extent1].[ExchangeSetId] = @p__linq__0) 
    AND (( CAST(CHARINDEX(SUBSTRING(@p__linq__1, 4 + 1, ( CAST(LEN(@p__linq__1) AS int)) - 4), [Extent1].[BasePrefix]) AS int)) = 1) 
    AND (( CAST(CHARINDEX([Extent1].[BasePrefix], @p__linq__2) AS int)) = 1) AND (( CAST(CHARINDEX([Extent1].[DestPrefix], @p__linq__3) AS int)) = 1)',N'@p__linq__0 int,@p__linq__1 nvarchar(4000),@p__linq__2 nvarchar(4000),@p__linq__3 nvarchar(4000)',@p__linq__0=1,@p__linq__1=N'0732055827',@p__linq__2=N'0732055827',@p__linq__3=N'0732612680'

如您所见,它正在为 StartsWith 生成 CHARINDEX。

问题是这忽略了我设置的所有索引,并且需要几秒钟才能运行 500 万条记录。

我怎样才能利用链接到实体,并满足我的上述要求,包括索引?

我唯一能想到的就是使用存储过程或原始 SQL 语句,这会打败整个实体。

【问题讨论】:

  • 这两个条件不是互相映照吗? x.BasePrefix.StartsWith(baseNumber.Substring(4)) && baseNumber.StartsWith(x.BasePrefix)
  • 我不是 SQL 专家,但它有助于加快查询速度(我认为)
  • 如果您想知道 stackoverflow.com/questions/22165269/sql-server-performance-tips-for-like,它是源自该线程的查询

标签: sql linq entity-framework indexing


【解决方案1】:

目前我找到的唯一合适的解决方案如下

var exchange = context.Database.SqlQuery<Exchange>(
    "SELECT TOP 1 * FROM Exchanges where ExchangeSetId = @ExchangeSetId and BasePrefix like left(@BaseNumber, 3) + '%' and @BaseNumber like BasePrefix +'%' and @DestNumber like DestPrefix +'%'",
    new SqlParameter("ExchangeSetId", exchangeSetId),
    new SqlParameter("AreaCode", areaCode),
    new SqlParameter("BaseNumber", baseNumber.Substring(2)),
    new SqlParameter("DestNumber", destNumber.Substring(2))).Select(x => new ExchangeViewModel(x)).FirstOrDefault();

【讨论】:

    【解决方案2】:

    我相信如果你使用这样的 Linq-to-SQL 格式,它会给你正确的 T-SQL:

    var exchange = (from x in context.Exchanges 
        where x.ExchangeSetId == exchangeSetId && 
       x.BasePrefix.StartsWith(baseNumber.Substring(4)) && 
       baseNumber.StartsWith(x.BasePrefix) &&
       destNumber.StartsWith(x.DestPrefix))
       select new x{}).FirstOrDefault();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 2020-01-17
      • 1970-01-01
      • 2014-01-04
      • 2016-08-20
      • 2017-07-17
      • 2011-08-17
      相关资源
      最近更新 更多