Не сразу обновляется поле в таблице Access

narval
Дата: 20.12.2004 04:08:06
Суть моих действий:
Две процедуры на vb.net, выполняются последовательно

Первая - выбирает из локальной базы Access новые записи из таблицы справочника и отправляет их на sql server, обратно получает ID которые получают записи на сервере и пишет эти ID (в качестве обновления поля этого справочника) в местную базу
Железно работает, многократно проверено.

Вторая - Выбирает записи из подчиненной таблицы местной базы Access с ID полученными в процедуре 1 и отправлет их на сервер.

Так вот, вторая процедура не видит полученые ID из предыдущего шага, отсылает упорно Null. Если между вызовами этих процедур поставить вызов закрытия коннекта к ACCESS и тут же его открытие - ОК, без вопросов, все нормально. Блокировок (по крайней мере насколько могу судить не очень разбираясь в jet) не возникает. Не хочу грузить приведением большого количества кода, тем не менее прошу поделиться тех кто имел такую проблему
OstapBender
Дата: 21.12.2004 19:52:21
Nedostatochno informazii. Hotelos' bi kusok koda, togda otvet bil bi bolee tochnim.Esli dopustit' chto ispol'zuyutsya transaction to po umolchaniyu ADO ispol'zuet "ReadComitted" level. Eto znachit chto "data zapisannaya odnoi transakziei budet dostupna posleduyuschei tol'ko posle togo kak pervaya budet zakonchena (commit)". Zitata iz knigi. Mozet v etom problema?
Max Pro
Дата: 22.12.2004 15:13:54
Между вызовами надо воткнуть Doevents
Если одного оператора мало, то подряд парочку.
А вообще-то положено коннект закрывать-открывать.
Max Pro
narval
Дата: 23.12.2004 13:05:26
Max Pro - Doevents не помогает...
OstapBender маленьким куском кода не отделаться, хорошо, если не лень посмотри:

На сервере:
CREATE TABLE ParentTable (IdSteady uniqueidentifier null, ParentText varchar(255))
GO
CREATE TABLE ChildTable (IdSteady uniqueidentifier null default newid(),
	ParentId uniqueidentifier null ,
	ChildText varchar(255))
GO
CREATE Proc InsertInParentTable
(@ParentText varchar(255))
as
Set nocount on

declare @NewId uniqueidentifier

select @NewId = newid()

insert into dbo.ParentTable
(IdSteady, ParentText)
values
(@NewId, @ParentText)

select @NewId
GO
CREATE Proc InsertInChildTable
(@ParentId uniqueidentifier, @ChildText varchar(255))
as
Set nocount on

insert into dbo.ChildTable
(ParentId, ChildText)
values
(@ParentId, @ChildText)
GO

В MDB файле:
две таблицы:
ParentTable
Поля:
   IdRow - Счетчик
   IdSteady - Числовой (Код репликации)
   ParentText - Текстовый(255)

ChildTable
Поля:
   IdRow - Счетчик
   IdParent - Числовой (Код репликации)
   ChildText - Текстовый(255)

Три сохраненных запроса:

SelectFromLocalParentTable:
SELECT ParentTable.ParentText, ParentTable.IdRow
FROM ParentTable;

SelectFromLocalChildTable:
SELECT ParentTable.IdSteady, ChildTable.ChildText
FROM ParentTable INNER JOIN ChildTable ON ParentTable.IdRow = ChildTable.IdParent;

Update_IdSteady:
UPDATE ParentTable SET ParentTable.IdSteady = [A]
WHERE (((ParentTable.IdRow)=[B]));


VB код:
Private SQLCnn As New SqlClient.SqlConnection
    Private AccessCnn As New OleDb.OleDbConnection
    Private AccessCnn1 As New OleDb.OleDbConnection
    Private SQLCmm As New SqlClient.SqlCommand
    Private AccessCmm As New OleDb.OleDbCommand
    Private AccessCmm1 As New OleDb.OleDbCommand

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        CnnAndCmmProperty()

        SQLCnn.Open()
        AccessCnn.Open()
        AccessCnn1.Open()

        TransferParentData()
        TransferChildData()

        AccessCnn1.Close()
        AccessCnn.Close()
        SQLCnn.Close()

    End Sub


    Private Sub CnnAndCmmProperty()
        SQLCnn.ConnectionString = ...
        AccessCnn.ConnectionString = ... Provider="Microsoft.Jet.OLEDB.4.0" ... 
        AccessCnn1.ConnectionString =  ... Provider="Microsoft.Jet.OLEDB.4.0" ... 
        
        SQLCmm.Connection = SQLCnn
        SQLCmm.CommandType = CommandType.StoredProcedure

        AccessCmm.Connection = AccessCnn
        AccessCmm.CommandType = CommandType.StoredProcedure

        AccessCmm1.Connection = AccessCnn1
        AccessCmm1.CommandType = CommandType.StoredProcedure

    End Sub

    Private Sub TransferChildData()
        SQLCmm.Parameters.Clear()

        SQLCmm.CommandText = "InsertInChildTable"
        SQLCmm.Parameters.Add("@ParentId", System.Data.SqlDbType.UniqueIdentifier)
        SQLCmm.Parameters.Add("@ChildText", System.Data.SqlDbType.VarChar, 255)

        AccessCmm.CommandText = "SelectFromLocalChildTable"

        Dim AccessReader As OleDb.OleDbDataReader = AccessCmm.ExecuteReader
        While AccessReader.Read()
            SQLCmm.Parameters(0).Value = AccessReader(0)
            SQLCmm.Parameters(1).Value = AccessReader(1)
            SQLCmm.ExecuteNonQuery()
        End While
        AccessReader.Close()

    End Sub
    Private Sub TransferParentData()

        SQLCmm.CommandText = "InsertInParentTable"
        SQLCmm.Parameters.Add("@ParentText", System.Data.SqlDbType.VarChar, 255)

        AccessCmm.CommandText = "SelectFromLocalParentTable"

        AccessCmm1.CommandText = "Update_IdSteady"
        AccessCmm1.Parameters.Add(New OleDb.OleDbParameter)
        AccessCmm1.Parameters.Add(New OleDb.OleDbParameter)

        Dim AccessReader As OleDb.OleDbDataReader = AccessCmm.ExecuteReader
        While AccessReader.Read()
            SQLCmm.Parameters(0).Value = AccessReader(0)
            AccessCmm1.Parameters(0).Value = SQLCmm.ExecuteScalar
            AccessCmm1.Parameters(1).Value = AccessReader(1)
            AccessCmm1.ExecuteNonQuery()
        End While
        AccessReader.Close()

    End Sub


После срабатывания на сервере в таблице ChildTable в поле ParentId стоит везде Null
narval
Дата: 23.12.2004 15:04:41
Прошу прощения, во второй таблице Access поле
IdParent - Числовой (длинное целое) разумеется, это внешний ключ
Max Pro
Дата: 30.12.2004 19:19:36
Боже, ну ты и накрутил кодов! По-моему проще можно. Тогда и глюка этого не будет и в помине. А так конечно - у тебя запросы-то параллельно выполняются.
Вот как бы я сделал:

1. В Аксесе подключил бы нужные таблицы из SQL-сервера как связанные. Это дало бы сразу преимущество, что коннекшинов вместо трёх всего один будет.
2. Сделал бы запросик уже через Аксес, получающий ID. И потом следом 2-й. А между ними не забыл бы вставить DoEvents().
3. Кроме того напоминаю, что закрывать коннекшн полезно после каждого запроса - это правило особенно действует в ASP.NET (если под Win пишешь, то необязательно, хотя и желательно.)

Ну вот и всё.
P.S. извини, что долго не был на связи
Max Pro
Max Pro
Дата: 30.12.2004 19:21:12
Кстати, если не в лом, скинь пожалуйста как выглядит полностью твой коннекшнстринг для sql-server. А то мне по работе это скоро понадобится.
Max Pro
narval
Дата: 02.01.2005 20:24:02
Кодов по минимуму :-) Проще уж некуда, в реале это самопальная репликация Access <> SQL sever. Параллельность выполенения этим и вызвана, что это меняет принципиально? Насчет закрытия/открытия соеденения согласен, практика показывает что так только и работает, хотелось бы только знать - почему?

ПС: Примерную строку для соеденения с SQLserver проще всего получить поместив на форму SQL connection, и воспользоваться мастером для ConnectionString
Worobjoff
Дата: 03.01.2005 11:15:31
Есть такое правило: "Коммитить" транзакцию.
До ее завершения внесенным данным "не верить".
Закрытие соединения собственно и служит этим "коммитом".

С Новым годом!
narval
Дата: 04.01.2005 22:50:06
Да, точно! Спасибо Воробьёфф. Кстати оказалось что подтверждение транзакции в Акцессе не только закрытие коннешна