1

在执行数据库搜索时,如何通过字符串的值减去它的第一个字符(在我的情况下,第一个字符始终是 C 后跟数字)对列表进行排序。

我已经尝试了很多东西,但我几乎在黑暗中磕磕绊绊,我相信这里有人可以立即解决这个问题。

我的代码有效(但没有做我想要的):

        List<Customer> customerlist = null;
        try
        {
            customerlist = db.Customers
                            .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
                            .OrderBy(u => u.Cust_ID)
                            .ToList();
        }

我目前的错误代码(在我看来它应该可以工作,但导致搜索总是不返回任何结果):

        List<Customer> customerlist = null;
        try
        {
            customerlist = db.Customers
                            .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
                            .OrderBy(u => Int32.Parse(u.Cust_ID.TrimStart('C')))
                            .ToList();
        }

更多细节:

我的表中有一个名为 Cust_ID 的列,它以 C 开头,然后是一个不带前导零的数字,例如 C1、C2、... C43、... C999。

我允许用户执行搜索,其查询分配给 searchstring。

我已经尝试通过删除 int 解析进行调试

                            .OrderBy(u => u.Cust_ID.TrimStart('C'))

也不返回任何结果。

我在这里的原始代码仍然可以完成搜索,但不能正确排序。

                            .OrderBy(u => u.Cust_ID)

我尝试使用 Replace 而不是 TrimStart

                            .OrderBy(u => u.Cust_ID.Remove(0, 1))

这会返回一个结果,但仍然没有排序,当我放入 Int 解析时,它会停止再次返回结果:

                            .OrderBy(u => Int32.Parse(u.Cust_ID.Remove(0, 1)))

我尝试将 int 解析切换为:

                            .OrderBy(u => int.Parse(u.Cust_ID.Remove(0, 1)))

但这没有帮助。

编辑:发现我遇到了一个异常:

System.NotSupportedException: LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.Convert()
       at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
       at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
       at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at lab2.Controllers.DemoController.retrievecustomers() in [[Directory]]Controller.cs:line 52
4

5 回答 5

2

您可以只使用AsEnumerableLINQ to Objects之前 OrderBy切换到. 换句话说,您将在OrderBy客户端执行而不是让 ORM 尝试(不成功)将其映射到 SQL 的 ORDER BY。

话虽如此,在数据库中存储一个永不改变的前缀是个坏主意。它浪费空间,迫使您使用错误的数据类型(VARCHAR 而不是 INT),在 ORDER BY 中触发错误的比较并阻止 ORDER BY 使用索引(尽管您的 WHERE 似乎已经非常有效地这样做了).. .

于 2012-08-24T02:04:15.537 回答
1

我只会在客户端进行订购。为什么?因为它不会增加通过网络的流量,并且会给您更多的灵活性并允许您检查不可靠的值。可以说,无论如何最好在客户端上进行排序,因为它可以减少服务器负载。

customerlist = db.Customers
    .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
    .AsEnumerable()  //EDIT: was ToArray()
    .OrderBy(u => Int32.Parse(u.Cust_ID.SubString(1)))
    .ToList();

请注意, AsEnumerable 会导致到该点的 linq 查询被发送到服务器,之后的一切都在客户端上完成。

作为旁注,我要补充一点,如果您不需要修改列表,那么将值存储在数组而不是列表中会更有效。

我还要补充一下,您真的想用他们的名字加入 CustID 进行搜索吗?这将导致搜索词 Bob 匹配名为 Bo Brown 的人。

编辑:我已将 ToArray 更改为 AsEnumerable,因为正如 Branko Dimitrijevic 指出的那样,这更有效。如果从其他答案中提取部分内容是不道德的,我深表歉意。

于 2012-08-24T02:03:21.380 回答
0

我对 LINQ 不太了解,但试试这个

.OrderBy(u => Convert.ToInt32(u.Cust_ID.Substring(1)))
于 2012-08-24T00:54:37.777 回答
0

我的猜测是您的数据库包含的值不是“C[0-9]+”形式并且与 int.Parse 不兼容,可能是“null”,导致您的 OrderBy 引发异常

于 2012-08-24T00:59:09.727 回答
0

我同意 MikeKulls 的观点,即可以在提取数据后进行排序,但如果您喜欢在服务器上进行排序,您可以填充字符串以获得整数排序的语义:

customerlist = db.Customers
                .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
                .OrderBy(u => u.Cust_ID.Substring(1).PadLeft(10 /* or suitable number */, '0'))
                .ToList();
于 2012-08-24T02:38:52.890 回答