@Archestron

Как правильно создать пользовательскую функцию SQLite на C#?

Господа программисты, на днях столкнулся с небольшой проблемой. Не удается создать пользовательскую функцию в SQLite на C#.NET так, чтобы она работала, как задумано. Функция скалярная, сравнивает две строки на схожесть по алгоритму LongestCommonSubsequence с проекта DuoVia.FuzzyStrings. Долго искал пример кода, где пояснялось бы, как это сделать, но везде описывались C-style функции (имеется ввиду sqlite_create_function() из сишного интерфейса к ядру sqlite).

В итоге нашел только вот это: Как подружить Linq-to-Entities и Regex. Там (ближе к началу) только скалярная функция описывалась, но мне пока только это и надо.

Все выглядело понятно и просто, поэтому я сделал по такому же принципу:

//Создание функции 
public class CloseToSQLiteFunction : SQLiteFunction
    {
        public static SQLiteFunctionAttribute GetAttribute()
        {
            return new SQLiteFunctionAttribute("CLOSETO", 2, FunctionType.Scalar); 
        }
        public override object Invoke(object[] args)
        {
            try
            {
                return FuzzyStrings.LongestCommonSubsequenceExtensions.LongestCommonSubsequence(args[0].ToString(), args[1].ToString()).Item2;
            }
            catch (Exception ex)
            {
                return ex;
            }
        }
    }
//***Разный код***//
//Добавление функции в базу при ее создании или подключении:
sql.DB_Conn.BindFunction(CloseToSQLiteFunction.GetAttribute(), new CloseToSQLiteFunction());


Так вот, в дальнейшем эта функция должна принимать 2 аргумента типа String и выдавать Double в запросах типа:

SELECT * FROM BaseTable WHERE CLOSETO('...какая-то строка...',Column1) > 0.33;
SELECT CLOSETO('...какая-то строка...',Column1) from BaseTable


Но и в режиме отладки и в любом другом она ДЕЙСТВИТЕЛЬНО создана, как скалярная функция с двумя входными параметрами, НО один из аргументов ВСЕГДА равен DbNull, и функция CLOSETO всегда возвращает 0.0d.

Пример кода:
static public T Execute<T>(string SQL_Query, params object[] fmtParams)
        {
            using (var comm = new SQLiteCommand(string.Format(SQL_Query, fmtParams), DB_Conn))
                try
                {
                    return (T)Convert.ChangeType(comm.ExecuteScalar(), typeof(T));
                }
                catch (InvalidCastException)
                {
                    return default(T);
                }
        }
 
//***Разный код***//
    //...
    long myID = Execute<long>("select ID from Person where closeto('{0}',PersonName) > 0.33;", PersonName); //Всегда выдает 0!
    //...


Что может быть причиной такого поведения функции?

Введу некоторое пояснение к первому участку кода:

//Создание функции 
public class CloseToSQLiteFunction : SQLiteFunction
    {
        public static SQLiteFunctionAttribute GetAttribute()
        {
            return new SQLiteFunctionAttribute("CLOSETO", 2, FunctionType.Scalar); 
        }
        //Режим отладки показывает, что args[0] - всегда имеет тип DbNull, несмотря на то, что функции передается две строки
        //Запрос: string.Format("select closeto(FirstName||' '||SecondName||' '||ThirdName,'{0}') as Closes from Person",PersonName);
        //PersonName - строка, содержащая исключительно символы [A-Za-zА-Яа-я0-9].
        public override object Invoke(object[] args)
        {
            try
            {
                return FuzzyStrings.LongestCommonSubsequenceExtensions.LongestCommonSubsequence(args[0].ToString(), args[1].ToString()).Item2;
            }
            catch (Exception ex)
            {
                return ex;
            }
        }
    }
  • Вопрос задан
  • 517 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Archestron Автор вопроса
Я знаю, как и на чем написана SQLite...
Необходим ответ в рамках вопроса (см. C#).
Уважительно прошу не заострять внимание на побочных деталях, отвечать по теме.
Кроме того, проект DuoVia.FuzzyStrings написан на C#, и его функции-то мне и нужно переработать в пользовательские скалярные SQLite.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы