2009-07-02 3 views
0

Access 2007에서 응용 프로그램을 개발하고 있습니다. SQL Server 2005 백 엔드에 연결하는 .accdb 프런트 엔드를 사용합니다. 런타임에 ADO 레코드 집합에 바인딩 된 양식을 사용합니다. 효율성을 위해 들어, 레코드는 보통 하나 개의 레코드를 포함하고, 서버에 나가 쿼리됩니다 :원본에 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이지만 읽기 전용입니다. 오른쪽면 ('많은'면)의 필드조차도 편집 할 수 없습니다.

TSQL에서 INNER JOIN 절을 제거하면 (strSource를 한 테이블로 제한) 폼을 완전히 편집 할 수 있습니다.

TSQL이 두 테이블의 priimary key 필드를 포함하고 각 테이블에 동시성을위한 timestamp 필드가 포함되어 있는지 확인했습니다.

.CursorType 및 .CursorLocation 속성을 사용하지 않도록 변경하려고 시도했습니다.

내가 뭘 잘못하고 있니?

+0

"Supports 메서드는 특정 기능에 대해 True를 반환 할 수 있지만 공급자가 모든 상황에서 기능을 사용할 수 있도록 할 수는 없습니다. Supports 메서드는 공급자가 특정 기능을 지원할 수 있는지 여부를 반환합니다. 예를 들어 Supports 메서드는 커서가 다중 테이블 조인 (일부 열은 업데이트 할 수 없음)을 기반으로하더라도 Recordset 개체가 업데이트를 지원함을 나타낼 수 있습니다. " - http://msdn.microsoft.com/en-us/library/ms676500%28VS.85%29.aspx – barrowc

+1

이런 종류의 코드 : "If Not Nz (.RecordSource, vbNullString) = vbNullString 그런 다음 "내 머리가 아프다."왜 IsNull (.RecordSource)가 아닌지? .RecordSource가 null 일 수없고 비어있는 경우 ZLS 인 경우 "Len (.RecordSource) = 0" –

답변

0

Unique Table 동적 속성을 레코드 집합에 설정하려고한다고 생각합니다.

+0

제안 해 주셔서 감사합니다. 시도했지만 아무런 차이가 없었습니다. –

0

내가 발견 한 해결 방법은 'IN'절을 사용하는 것입니다. 예를 들어

SELECT c.* 
FROM CATEGORY  c 
WHERE c.category_id IN (
      SELECT p.category_id 
      FROM PRODUCT  p 
      JOIN CUST_ORDER o ON o.product_id = p.product_id 
      WHERE p.product_type = 'Widget' 
      AND  o.units   > 50 
     ) 

분명히 하드 코드 값은 서브 루틴에 전달 (및 이용할 변수 결합) 될 수있다. 주의해야 할 중요한 점은 IN 절이 여러 개의 조인을 가질 수 있으며 Resultset은 여전히 ​​업데이트 가능하다는 것입니다.

두 개 이상의 테이블에서 필드가 필요한 경우 데이터베이스보기를 만들거나 DLookup()을 사용하여 시도 할 수 있습니다.

관련 문제