2009-07-02 3 views
0

Access 2007でアプリケーションを開発しています。SQL Server 2005バックエンドに接続する.accdbフロントエンドを使用します。実行時にADOレコードセットにバインドされたフォームを使用します。効率のために、レコードセットは、通常、1つのレコードのみが含まれており、サーバー上で照会されます。ソースにJOINが含まれている場合、更新可能なADOレコードセットにバインドされたフォームは更新できません。

Public Sub SetUpFormRecordset(cn As ADODB.Connection, rstIn As ADODB.Recordset,  rstSource As String) 
Dim cmd As ADODB.Command 
Dim I As Long 

Set cmd = New ADODB.Command 

cn.Errors.Clear 

' Recordsets based on command object Execute method are Read Only! 

With cmd 
    Set .ActiveConnection = cn 
    .CommandType = adCmdText 
    .CommandText = rstSource 
End With 

With rstIn 
    .CursorType = adOpenKeyset 
    .LockType = adLockPessimistic       'Check the locktype after opening; optimistic locking is worthless on a bound 
End With             ' form, and ADO might open optimistically without firing an error! 

rstIn.Open cmd, , adOpenKeyset, adLockPessimistic   'This should run the query on the server and return an updatable recordset 

With cn 
    If .Errors.Count <> 0 Then 
     For Each errADO In .Errors 
      Call HandleADOErrors(.Errors(I)) 
      I = I + 1 
     Next errADO 
    End If 
End With 
End Sub 

rstSource(レコードセットがベースとなっているTSQLをcontaing文字列)を呼び出しルーチンによって組み立てられ、

Private Sub Form_Open(Cancel As Integer) 
Dim rst As ADODB.Recordset 
Dim strSource As String, DefaultSource as String 
Dim lngID As Long 

lngID = Forms!MyParent.CurrentID 

strSource = "SELECT TOP (100) PERCENT dbo.Customers.CustomerID, dbo.Customers.LegacyID, dbo.Customers.Active, dbo.Customers.TypeID, dbo.Customers.Category, " & _ 
"dbo.Customers.Source, dbo.Customers.CustomerName, dbo.Customers.CustAddrID, dbo.Customers.Email, dbo.Customers.TaxExempt, dbo.Customers.SalesTaxCode, " & _ 
"dbo.Customers.SalesTax2Code, dbo.Customers.CreditLimit, dbo.Customers.CreationDate, dbo.Customers.FirstOrder, dbo.Customers.LastOrder, " & _ 
"dbo.Customers.nOrders, dbo.Customers.Concurrency, dbo.Customers.LegacyLN, dbo.Addresses.AddrType, dbo.Addresses.AddrLine1, dbo.Addresses.AddrLine2, " & _ 
"dbo.Addresses.City, dbo.Addresses.State, dbo.Addresses.Country, dbo.Addresses.PostalCode, dbo.Addresses.PhoneLandline, dbo.Addresses.Concurrency " & _ 
"FROM dbo.Customers INNER JOIN " & _ 
"dbo.Addresses ON dbo.Customers.CustAddrID = dbo.Addresses.AddrID " 
strSource = strSource & "WHERE dbo.Customers.CustomerID= " & lngID 

With Me        'Default is Set up for editing one record 
    If Not Nz(.RecordSource, vbNullString) = vbNullString Then 
     If .Dirty Then .Dirty = False 'Save any changes on the form 
     .RecordSource = vbNullString 
    End If 

    If rst Is Nothing Then   'Might not be first time through 
     DefaultSource = .RecordSource 
    Else 
     rst.Close 
     Set rst = Nothing 
    End If 
End With 

Set rst = New ADODB.Recordset 
Call setupformrecordset(dbconn, rst, strSource) 'dbconn is a global variable 

With Me 
    Set .Recordset = rst 
End With 

End Sub 

setupformrecordsetから返されるレコードセットが完全に更新可能であり、その.Supportsプロパティは、これを示していますフォームのOpenイベントから、この場合に束縛されます。これはコードで編集して更新することができます。

しかし、フォーム全体が.AllowEditsと.AllowAdditionsの両方のプロパティがtrueであっても、読み取り専用です。右手側(「多く」側)のフィールドでさえ、編集することはできません。

INNER JOIN句をTSQLから削除すると(strSourceを1つのテーブルに制限する)、フォームは完全に編集可能になります。

私は、TSQLに両方のテーブルのプライマリキーフィールドが含まれていることを確認しました。各テーブルには同時実行のタイムスタンプフィールドが含まれています。

レコードセットの.CursorTypeと.CursorLocationプロパティを無駄に変更しようとしました。

私は間違っていますか?

+0

"Supportsメソッドは、特定の機能に対してTrueを返すことがありますが、プロバイダがすべての状況でこの機能を利用できるようにすることはできません。たとえば、Supportsメソッドは、カーソルが複数のテーブル結合に基づいていても、更新可能ではない列があっても、Recordsetオブジェクトが更新をサポートしていることを示している可能性があります。 - http://msdn.microsoft.com/en-us/library/ms676500%28VS.85%29.aspx – barrowc

+1

この種のコード: "If Not Nz(。RecordSource、vbNullString)= vbNullStringそれから "私の頭が痛いのですが、なぜ" Not IsNull(.RecordSource) "なのでしょうか?.RecordSourceを空にすることはできませんし、空の場合はZLSです" Len(.RecordSource)= 0 " –

答えて

0

Unique Tableダイナミックプロパティをレコードセットに設定すると思います。

+0

提案してくれてありがとう - 私はそれを試しましたが、違いはありませんでした。 –

0

私が見つけた回避策は、 'IN'句を使用することです。明らかに、ハードコードされた値は、サブルーチン(および使用されるバインド変数)に渡すことができます。注意すべき重要なことは、IN句に任意の数の結合を持たせることができ、Resultsetは引き続き更新可能であることです。

複数のテーブルのフィールドが必要な場合は、データベースビューを作成したり、DLookup()を使用したりできます。

関連する問題