转换'字符串'到' int'在.Any()LINQ查询中

时间:2016-04-28 18:25:04

标签: c# entity-framework linq sql-server-2012 entity-framework-6

我有一个条件语句,它根据我的数据库评估.Any()LINQ查询。

在将字符串转换/转换为long值时抛出错误。 (long.TryParse(m.Reference,out t)?t:long.MaxValue)

错误类似于: LINQ to Entities无法识别方法' ....'方法,此方法无法转换为商店表达式

我在这里做错了吗?我怎样才能做到这一点?

using (var ctx = new DatabaseEntities())
{
   long t;
  if(!ctx.CustomerInboxes.Any(m=>m.CustomerId == customerId
   && m.Reference == item.ShoppingCartWebId.ToString() 
   && m.SubjectId == HerdbookConstants.PendingCartMessage 
   && item.ShoppingCartWebId > (long.TryParse(m.Reference,out t)? t : long.MaxValue)))
 )){
     //do something special
  }
}

6 个答案:

答案 0 :(得分:1)

using (var ctx = new DatabaseEntities())
{
   long t;
  if(!ctx.CustomerInboxes.ToList().Any(m=>m.CustomerId == customerId
   && m.Reference == item.ShoppingCartWebId.ToString() 
   && m.SubjectId == HerdbookConstants.PendingCartMessage 
   && item.ShoppingCartWebId > (long.TryParse(m.Reference,out t)? t : long.MaxValue)))
 )){
     //do something special
  }
}

只需添加.ToList()即可。虽然这会将您的整个列表带回客户端,但它允许您执行您想要执行的自定义运算符。

根据这里的评论,另一种方法是从数据库中恢复一个子集,然后执行自定义解析运算符。

            long t;
            var initialQuery = ctx.CustomerInboxes.Where(x => m.CustomerId == customerId
              && m.Reference == item.ShoppingCartWebId.ToString()
              && m.SubjectId == HerdbookConstants.PendingCartMessage).ToList();

            if (!initialQuery.Any(m => item.ShoppingCartWebId > (long.TryParse(m.Reference, out t) ? t : long.MaxValue)))
            {
                //do something special
            }

答案 1 :(得分:1)

根据您的代码,当m.Reference不是有效数字时,条件应该失败,可以使用SqlFunctions.IsNumeric()来完成。

要比较数字,您可以使用string.Compare并使用0模拟数字比较填充(可以使用SqlFunctions.Replicate())。

它不太漂亮,但应该有效:

var itemId = item.ShoppingCartWebId.ToString();

ctx.CustomerInboxes.Any(m => ...
                          && SqlFunctions.IsNumeric(m.Reference) != 0 
                          && string.Compare(SqlFunctions.Replicate("0", m.Reference.Length > itemId.Length ? m.Reference.Length - itemId.Length : 0) + itemId, m.Reference) > 0);

但是,您始终可以切换到 Linq to Objects 以检查此特定部分:

ctx.CustomerInboxes.Where(m => m.CustomerId == customerId &&
                               m.Reference == item.ShoppingCartWebId.ToString()  &&
                               m.SubjectId == HerdbookConstants.PendingCartMessage)
                    .AsEnumerable()
                    .Any(c => item.ShoppingCartWebId > (long.TryParse(c.Reference, out t) ? t : long.MaxValue))

答案 2 :(得分:0)

长度检查与string.Compare的组合应该可以解决问题。

逻辑

  • 如果item.Reference.Length的长度更长,则它也是一个更大的数字。
  • 如果它们的长度相同,那么执行string.Compare从左到右进行躲避,这也适用于数字。

string.Compare(string a, string b)。这将返回:

    如果a大于b ,则
  • 1 如果a等于b
  • ,则
  • 0 如果b大于a
  • ,则
  • -1

代码:

using (var ctx = new DatabaseEntities())
{
    var webId = item.ShoppingCartWebId.ToString();
    var webIdLength = webId.Length;

    if (!ctx.CustomerInboxes.Any(m => m.CustomerId == customerId
        && m.Reference == item.ShoppingCartWebId.ToString()
        && m.SubjectId == HerdbookConstants.PendingCartMessage
        && (m.Reference.Length > webIdLength || (m.Reference.Length == webIdLength && string.Compare(m.Reference, webId) > 0))))) {
            //do something special
        }
}

效益

索引!由于此处不涉及填充,因此实际比较检查仍然可以从此列上的任何索引中受益。如果您的数据增长,则不应过多影响性能。不幸的是,长度比较不会使用我认为但比较的任何索引但是可能对性能的影响小于查询的其他部分

假设

  • 没有,.
  • 等格式字符
  • 没有使用0或空格
  • 填充字符串的情况
  • 您总是在比较整数(没有分数)

答案 3 :(得分:0)

一种可能的解决方案是在CustomerInboxes源表中添加计算列(我假设它是一个表,但它可以是视图或存储过程),这样您就不必使丑陋了LINQ2SQL无法翻译的比较:

ReferenceAsLong AS ISNULL(TRY_CONVERT(BIGINT, Reference), CAST(9223372036854775807 AS BIGINT)) PERSISTED 

您麻烦LINQ条件已经简化,应该可以正常工作:

item.ShoppingCartWebId > ReferenceAsLong

答案 4 :(得分:0)

您可以尝试使用Convert.ToInt64而不是long.TryParse。

答案 5 :(得分:0)

此查询看起来很糟糕。理想情况下,您应该在DB中将其切换为int字段。

(只要没有前置0s)
您可以修改逻辑,以便如果ShoppingCartWebId的长度超过满足条件的长度,或者如果长度相等,则字符串比较应该可以正常工作

using (var ctx = new DatabaseEntities())
{
   long t;
  if(!ctx.CustomerInboxes.Any(m=>m.CustomerId == customerId
   && m.Reference == item.ShoppingCartWebId.ToString() 
   && m.SubjectId == HerdbookConstants.PendingCartMessage 
   && (item.ShoppingCartWebId.length > SqlFunctions.StringConvert((long).Reference) 
   || (item.ShoppingCartWebId.length == SqlFunctions.StringConvert((long).Reference
       && item.ShoppingCartWebId > SqlFunctions.StringConvert((long)m.Reference)
 ))){
     //do something special
   }
}