MySQL и Entity Framework - Приложение, вызывающее хранимую процедуру, возвращает 0 выполненных строк, но та же процедура работает в терминале - PullRequest
1 голос
/ 07 марта 2012

Недавно мне пришлось переключиться с использования SQL-сервера Microsoft на MySQL.

Приложение, которое я написал, использует Entity Framework 4.0.Мне очень нравится MySQL, но процесс был немного болезненным.Большинство операций CRUD выполняются с помощью хранимых процедур, поэтому я получил удовольствие от встречи с MySQL bug 55778 .

. Я справился с этим и вручную отредактировал файл EDMX.

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

Вот где это происходит:

using (var context = new DBEntities())
            {
                context.Requests.AddObject(request);
                context.SaveChanges();

                response.RequestId = request.Id;
                context.Responses.AddObject(response);
                context.SaveChanges();

            } 

Запрос регистрируется нормально.Исключение выдается, когда я пытаюсь сохранить изменения в ответе.RequestId - это первичный ключ (не увеличивается автоматически) таблицы ответов.Я пытался использовать профилировщик MySQL, чтобы увидеть, что происходит, но на самом деле это не сработало.Я мог только профилировать запросы, сделанные через мой терминал, но не запросы, сделанные приложением, работающим на моем локальном IIS.

В итоге я использовал Wireshark .Я обнаружил, что при сохранении ответа вызывается хранимая процедура, связанная с Вставкой в ​​объекте ответа.MySQL возвратил ответ, говорящий, что были обработаны 0 строк.Это вызвало исключение.Затем приложение вызывает ROLLBACK, удаляя любые изменения, которые должны были быть сделаны.

Если я запускаю эту хранимую процедуру в терминале с точно такими же значениями, она работает.

Так что по проводам я вижу этобудучи вызванным:

CALL `DevDB`.`LogResponse` (1,'2012-03-06 12:30',1,1,'test','test','test','test',false,'test');

Затем возвращаются 0 строк и вызывается ROLLBACK.

Выполнение той же самой команды из MySQL Workbench работает.Я пробовал это несколько раз, сбросив базу данных и начав сначала.Я не могу найти причину для этого.Запрос регистрируется с использованием аналогичного метода, и он работает.

Приложение имеет разрешения EXECUTE для обеих хранимых подпрограмм.

Кто-нибудь сталкивался с чем-то подобным раньше?

РЕДАКТИРОВАТЬ: я также использую обработчики MySQL чтобы поймать любую ошибку, которую я мог придумать, и записать ее в таблицу журнала ошибок.например,

DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
    ROLLBACK;
    INSERT INTO `DevDB`.`tblDatabaseErrorLogs`(ERROR_MESSAGE, ERROR_CODE)
    VALUES(
    'SQL Exception at LogResponse',    
    'Unknown'
    );
END; 

Пока что ни один из кодов ошибок, которые я планировал - исключение SQL, предупреждение WAR и многие другие, - по-видимому, произошел, поскольку таблица журнала ошибок пуста.

1 Ответ

0 голосов
/ 07 марта 2012

Я обнаружил, что является причиной проблемы, но я действительно не понимаю, почему.Если кто-то даст хорошее объяснение, тогда я приму это как ответ на этот вопрос, а не приму свое.

Это то, что, по-видимому, вызвало проблему.

При использовании хранимых процедур дляделать вставки в Entity Framework Я обнаружил, что для того, чтобы дать Entity в приложении правильный Id во время выполнения, мне пришлось возвращать Id в хранимой процедуре.

В MySQL я делаю это следующим образом:

CREATE PROCEDURE LogResponse(IN myVals)
BEGIN 
Insert Into `DevDB`.`tblResponses`
(
    someValueNames
)
Values
(
    someValues
);

 SELECT LAST_INSERT_ID() As NewResponseId;
END

Возвращенное значение SELECT отображает идентификатор PK объекта, который использует эту хранимую процедуру в качестве функции INSERT.

Просто так получилось, что я не использовал возвращаемое значение для ответа, потому что мне не нужен идентификатор в приложении.Я полагаю, что это было упущением, но не возникло никаких проблем, когда я проделал аналогичную работу с SQL Server

, т.е.

SELECT SCOPE_IDENTITY() As NewResponseId

Все, что я сделал, чтобы исправить ситуацию, это удалил строку

SELECT LAST_INSERT_ID() As NewResponseId;

Кажется, теперь все работает так, как должно.

...