0

Regarding this previous stackoverflow question:

DRY CLR table-valued functions

It seems it only runs in single thread mode. To test this I modified the code slightly to prepend the Name field with the current thread number. All of the returned results had the same thread number assigned. Is this action by design? Is there anyway to get it to multithread? Thanks.

private class ResultRow
// This class holds a row which we want to return.
{
    public SqlInt32 CustId;
    public SqlString Name;

    public ResultRow(SqlInt32 custId_, SqlString name_)
    {

        int mythread = Thread.CurrentThread.ManagedThreadId;
        CustId = custId_;
        Name = "[" + mythread.ToString() + "] " + name_;
    }
}

EDITED per Marc's question:

Here's the full piece of code. It returns 3470 records in 7 seconds.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Threading;

namespace CS_CLR_TVF
{

  public partial class UserDefinedFunctions
  {

    // This class holds a row which we want to return.
    private class ResultRow
    {
        public SqlString fldProductName;
        public ResultRow(SqlString product_)
        {
            int mythread = Thread.CurrentThread.ManagedThreadId;
            fldProductName = "[" + mythread.ToString() + "] " + product_;
        }
    }

    [SqlFunction(DataAccess = DataAccessKind.Read, FillRowMethodName = "Test_FillRow", TableDefinition = "fldProductName nvarchar(1024)")]
    public static IEnumerable xudf_cs_tvf(SqlString strSearchClue)
    {
        ArrayList results = new ArrayList();

        using (SqlConnection connection = new SqlConnection("context connection=true"))
        {
            connection.Open();
            string s1;

            using (SqlCommand select = new SqlCommand("SELECT fldProductName FROM tblProducts", connection))
            {
                using (SqlDataReader reader = select.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        s1 = reader.GetSqlString(0).ToString();

                        // do a substring compare, if "match" grab the row
                        int idx = s1.IndexOf(strSearchClue.ToString());
                        if (idx > -1) results.Add(new ResultRow(reader.GetSqlString(0)));
                    }
                }
            }
        }
        return results;
    }

    // This function takes a row and tells SQL Server what variables we want to 
    // return from it and what types it contains.
    public static void Test_FillRow(object resultsObj, out SqlString fldProductName)
    {
        ResultRow selectResults = (ResultRow)resultsObj;
        fldProductName = selectResults.fldProductName;
    }
  }
}

Pretty straight forward internal select statement:

SELECT fldProductName FROM tblProducts

. . . . Here's a version implemented as a scalar UDF and it does do multithreading. It returns 3470 records in <1 second.

[Microsoft.SqlServer.Server.SqlFunction]
public static long xudf_csfake(SqlString strSearchClue, SqlString strStringtoSearch)
{
    string s1 = strStringtoSearch.ToString();
    // do a substring compare, if "match" grab the row
    int idx = s1.IndexOf(strSearchClue.ToString());
    if (idx > -1) return 1;

    return 0;
}  

Here is it's external select statement:

SELECT  fldProductName FROM tblProducts  WHERE (dbo.xudf_csfake('METAL' ,fldProductName) = 1)

So I seem to getting the opposite of what the article indicates.

4

0 回答 0