Comparison operators not supported for type 'System.String[]'

后端 未结 5 2116
渐次进展
渐次进展 2020-12-11 22:20

why this line:

var category = _dataContext.Categories.Where(p => p.Keywords.Split(\' \').Contains(context.Request.QueryStrin         


        
相关标签:
5条回答
  • 2020-12-11 22:55

    string.split is not supported in LINQ-to-SQL.

    There's an easy fix. Select all the data and do the filtering in the client. This may not be very efficient depending on the number of categories.

    var category = 
        _dataContext.Categories.ToList()
        .Where<Category>(p => p.Keywords.Split(' ').Contains<string>(context.Request.QueryString["q"])).First();
    

    Calling .ToList() will force enumeration of all the categories from your datasource, and the subsequent operations will be performed in the client code.

    0 讨论(0)
  • 2020-12-11 22:56

    So you are looking for a value (from the query-string) in a space-delimited column in the database? And you're using Split to query the individual values inside the database?

    (just checking my assumptions...)

    string.Split is not supported in this way (at the database on column data) - see here for the supported string operations. (note that string.Split is explicitly not supported).

    I'm lazy; when I delimit data in the database (relatively rare), I always add the same delimiter to the start and end of the data; then I can just search for:

    string searchFor = DELIMITER + searchValue + DELIMITER;
    ...
    .Where(row => row.Value.Contains(searchFor));
    

    However; in this case, I expect the most practical option might be to write a UDF function that searches a delimited varchar (correctly handling the first/last item), and expose the UDF on the data-context - then use:

    .Where(row => ctx.ContainsValue(row.Value, searchValue)); // ContainsValue is our UDF
    

    Or - normalise the data...

    .Where(row => row.Values.Any(s=>s.Value == searchValue));
    
    0 讨论(0)
  • 2020-12-11 22:56

    Firstly, I'd avoid storing delimited data in the database. As you've found out it can make database queries etc awkward.

    If you have a limit amount of categories, I'd go with Joe's answer for simplicity, else, adding some detail to Marc's approach.

    1. Create a split-style UDF, for SQL Server I use:
    
    CREATE FUNCTION FN_CHARLIST_TO_TABLE
     (@list      nvarchar(MAX),
      @delimiter nchar(1) = N',')
    RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
                  str     varchar(4000)      NOT NULL,
                  nstr    nvarchar(2000)     NOT NULL) AS
    /*                
      Comments:
            - Takes a CSV string, and creates a table of data from this
            - Each item takes one row in the following format
                listpos - the index of the item in the string (effectively a row number in the output)
                str - The value, as VARCHAR
                nstr - The value, as NVARCHAR
    
            - This function is a direct extract from http://www.sommarskog.se/arrays-in-sql-2005.html#iter-list-of-strings
    Usage:
        SELECT * 
        FROM  t 
        JOIN FN_CHARLIST_TO_TABLE('a,b,c,1,2,3', ',') list
        ON t.Name = list.str        
    */
    BEGIN
       DECLARE @endpos   int,
           @startpos int,
           @textpos  int,
           @chunklen smallint,
           @tmpstr   nvarchar(4000),
           @leftover nvarchar(4000),
           @tmpval   nvarchar(4000)
    
       SET @textpos = 1
       SET @leftover = ''
       WHILE @textpos  0
          BEGIN
         SET @tmpval = ltrim(rtrim(substring(@tmpstr, @startpos + 1,
                             @endpos - @startpos - 1)))
         INSERT @tbl (str, nstr) VALUES(@tmpval, @tmpval)
         SET @startpos = @endpos
         SET @endpos = charindex(@delimiter COLLATE Slovenian_BIN2,
                     @tmpstr, @startpos + 1)
          END
    
          SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)
       END
    
       INSERT @tbl(str, nstr)
          VALUES (ltrim(rtrim(@leftover)), ltrim(rtrim(@leftover)))
       RETURN
    END
    
    
    1. Add this to your DBML file
    2. Query your database, referencing the UDF appropriately
    
    var catergories = from cat in _datacontext.Categories
                      from keyword in _datacontext.FN_CHARLIST_TO_TABLE(cat.Keywords, ' ')
                      where keyword.str == context.Request.QueryString["q"]
                      select cat;
    

    This will then execute a purely database-side query.

    0 讨论(0)
  • 2020-12-11 23:07

    1) ToList() your var query

    2) In generated list in 1 step write your contain and split query: it execute correctly

    good luck

    0 讨论(0)
  • 2020-12-11 23:14

    It's probably the case that context.Request.QueryString["q"] returns a string array instead of a single string. This is because a url may contain multiple parameters with the same name.

    If you are sure there is always just one parameter named q on the request, you can change your code to this: context.Request.QueryString["q"].SingleOrDefault().

    0 讨论(0)
提交回复
热议问题