Заполнить новое поле в базе данных SQLite, используя существующее значение поля и функцию C #

У меня есть база данных SQLite, для которой я хочу заполнить новое поле на основе существующего. Я хочу получить новое значение поля с помощью функции C #.

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

foreach ( record in the SQLite database)
{
my_new_field[record_num] = my_C#_function(existing_field_value[record_num]);
}

Рассмотрев другие предложения по StackOverflow, я использую SqliteDataReader для чтения каждой записи, а затем запускаю команду SQlite «UPDATE» на основе конкретного RowId для обновления нового значения поля для той же записи.

Он работает ... но он ДЕЙСТВИТЕЛЬНО медленный и как сумасшедший забивает жесткий диск. Неужели нет лучшего способа сделать это?

Некоторые из баз данных, которые мне нужно обновить, могут содержать миллионы записей.

Заранее благодарю за любую помощь.

Редактировать:

В ответ на комментарий вот реальный код на устаревшем языке под названием Concordance CPL. Важно отметить, что вы можете читать и записывать изменения в текущую запись за один раз:

int db;

cycle(db)
{
db->FIRSTFIELD = myfunction(db->SECONDFIELD);
}

myfunction(text input)
{
text output;

/// code in here to derive output from input

return output;
}

У меня такое чувство, что в SQLite нет эквивалентного способа сделать это, поскольку SQL по своей сути является транзакционным, тогда как Concordance позволяет вам просматривать и обновлять базу данных последовательно.


person Andrew17856    schedule 24.07.2019    source источник
comment
... похоже, я смогу повысить производительность, заключив все обновления в одну транзакцию. Тем не менее, я думаю, что мой вопрос все еще остается в силе, является ли несколько запросов на обновление правильной архитектурой для этого вообще. Спасибо.   -  person Andrew17856    schedule 25.07.2019
comment
Может быть множество других способов, это сложно отличить по фальшивому псевдокоду.   -  person Ňɏssa Pøngjǣrdenlarp    schedule 25.07.2019
comment
Трудно сказать, почему ваш предыдущий код был таким медленным, потому что ваш псевдопсевдокод был бесполезен (несмотря на добавление более абстрактного CPL). Он не выявил никаких фактических объектов C # или операторов SQL ... подробностей, которые критичны для обращения за помощью с производительностью и т. Д. Поскольку sqlite является внутрипроцессной встроенной СУБД, он позволяет пользовательские функции, которые необходимо определить, чтобы вы могли делать что-то вроде _1 _... очень аналогично фрагменту CPL.   -  person C Perkins    schedule 25.07.2019
comment
Спасибо. В ПОРЯДКЕ. Наверное, мне следовало более конкретно задать свой вопрос. У меня не было проблем с кодированием. Мой запрос был более разумной проверкой принципа: то есть, является ли способ only обновления всех строк в базе данных SQLite несколькими командами UPDATE, ссылающимися на разные RowID. Кажется, ответ - да, поскольку даже если вы используете SQLDataAdapter, он все равно просто создает команды UPDATE за сценой.   -  person Andrew17856    schedule 25.07.2019
comment
p.s. Мне также известно о возможности определять пользовательские функции в SQLite. Я не знаю, что есть интерфейс, который позволяет SQLite использовать функции C # .net (краткое содержание здесь)?   -  person Andrew17856    schedule 25.07.2019
comment
stackoverflow .com / questions / 172735 / Извините, я не могу углубиться в то, как я их использую прямо сейчас, с более полным образцом кода, но вот начало для C # с использованием system.data.sqlite (который может легко быть добавленным в проект Visual Studio с помощью nuget).   -  person C Perkins    schedule 25.07.2019
comment
Это действительно полезно - спасибо. Тогда это еще один способ сделать это. Создайте функцию C #, привяжите ее к SQLite, затем выполните команду обновления, которая обращается к ней.   -  person Andrew17856    schedule 25.07.2019


Ответы (1)


Ответ на этот вопрос - объединить все обновления в одну транзакцию.

Вот пример, который делает это для массовых вставок: https://www.jokecamp.com/blog/make-your-sqlite-bulk-inserts-very-fast-in-c/

В моем случае это будут массовые обновления на основе RowID, заключенные в одну транзакцию.

Теперь он работает, и производительность на много порядков лучше.

РЕДАКТИРОВАТЬ: согласно приведенному выше полезному комментарию определение пользовательской функции C # и последующая ссылка на нее в одной команде UPDATE также хорошо работает, и в некоторых отношениях лучше, чем указано выше, поскольку вам не нужно выполнять цикл внутри самого C #. См., Например, Создавать / использовать определяемые пользователем функции в System.Data.SQLite?

person Andrew17856    schedule 25.07.2019
comment
Тот факт, что это помогло улучшить ваш код, замечательно. Но даже код на связанной странице все еще неполный и не использует передовые методы. Возможно, вы могли бы ускорить его еще больше. Точка определения объекта SQLiteCommand состоит в том, чтобы создать параметризованный подготовленный оператор (т. Е. Аналогичный предварительно скомпилированному оператору), который вы затем только передаете данные и повторно выполняете. Связанный код постоянно переопределяет cmd.CommandText ... неэффективно. Посмотрите параметры SQLiteCommand. Простое завершение транзакции, скорее всего, не привело к увеличению производительности. - person C Perkins; 25.07.2019
comment
Спасибо. Да, я использую параметры в своем коде. Команда определяется в операторе using, и только параметры обновляются при просмотре каждой записи. - person Andrew17856; 25.07.2019