SQL Anywhere, Entity Framework 4 и транзакции

У меня есть процесс в моей программе, который использует Entity Framework 4 EDM. Объект контекста сущности содержит функции импорта для вызова хранимых процедур.

Процесс получает пакет данных с удаленного сервера. Пакет может состоять из данных для любой из наших таблиц/типов данных (каждый тип данных хранится в своей таблице). Пакет также может содержать данные для одной и той же строки несколько раз. Он должен обрабатывать это как одну вставку (для первого появления) и одно или несколько обновлений (для каждого последующего появления). Поэтому хранимые процедуры реализуют операцию upsert с помощью команды INSERT ... ON EXISTING UPDATE.

Наш код в основном определяет, какую хранимую процедуру вызывать, а затем вызывает ее, используя метод объекта контекста сущности для этой хранимой процедуры. Затем весь пакет должен быть выполнен за одну транзакцию, поэтому мы вызываем context.Connection.BeginTransaction() в начале пакета.

Есть один тип данных, содержащий миллионы строк. Нам нужно загрузить эти данные как можно быстрее. Я реализую логику для импорта этого типа данных с помощью класса SABulkCopy. Это также должно быть частью уже начатой ​​одиночной транзакции. Проблема в том, что мне нужно передать SATransaction в конструктор класса SABulkCopy (нет возможности установить его с помощью свойств), и у меня нет SATransaction. context.Connection.BeginTransaction() возвращает DBTransaction. Я безуспешно пытался преобразовать это в SATransaction.

Как правильно заставить объект SABulkCopy присоединиться к транзакции?


person Tony Vitabile    schedule 07.09.2012    source источник


Ответы (1)


Мы отказались от класса SABulkCopy. Оказывается, он не выполняет объемную загрузку. Он создает объект SACommand, который выполняет оператор INSERT и вставляет строки по одной. И делает это неэффективно, к тому же.

Мне все еще нужно было получить SATransaction, связанный с DBTransaction, возвращенным context.Connection.BeginTransaction().. Мне дали некоторый код отражения, который делает это в ответ на другой вопрос, который я опубликовал по этому поводу:

SATransaction saTransaction = (SATransaction) dbTransaction.GetType() 
                                                           .InvokeMember( "StoreTransaction", 
                                                                          BindingFlags.FlattenHierarchy | BindingFlags.NonPublic   | BindingFlags.InvokeMethod |
                                                                          BindingFlags.Instance         | BindingFlags.GetProperty | BindingFlags.NonPublic, 
                                                                          null, dbTransaction, new object[ 0 ] );

Программа делает то, что ей нужно. К сожалению, Microsoft не сделала свойство StoreTransaction класса EntityTransaction общедоступным.

person Tony Vitabile    schedule 27.03.2013
comment
Я знаю, что это старо, но не могли бы вы рассказать мне, как вы узнали, что SaBulkCopy создает и SACommand и выполняет вставку statment ...? Кстати, каким было ваше решение, когда вы решили отказаться от SaBulkCopy? Спасибо - person EagerToLearn; 07.09.2017
comment
Да, это было давно. Возможно, я использовал декомпилятор, такой как .Net Reflector, чтобы просмотреть декомпилированный код и выяснить, что происходило во время SaBulkCopy. Я думаю, что код является проектом с открытым исходным кодом, так что вы можете посмотреть его. Извините, я больше не в том положении, поэтому я не могу вспомнить. Кажется, я помню, что нам нужно было написать код, который вставлял данные построчно (не обойти это) во временную таблицу без индексов, а затем обновлял основную таблицу из этой таблицы, а затем удалял временную таблицу. Мы также сделали все это в одной транзакции. - person Tony Vitabile; 08.09.2017
comment
Большое спасибо за ответ @Tony Vitabile - person EagerToLearn; 11.09.2017
comment
Я думаю, что SaBulkCopy создаст SaCommand, вставит строку, отбросит SaCommand, а затем повторит для каждой строки. Мы написали код таким образом, что он создал один объект SaCommand, который можно было бы повторно использовать для всех строк. Для одной или двух строк улучшение незначительное, но для миллионов строк улучшение будет значительным. - person Tony Vitabile; 13.09.2017