Fixing #DELETED# After Data Change (1 Viewer)

Frothingslosh

Premier Pale Stale Ale
Local time
Today, 04:34
Joined
Oct 17, 2012
Messages
3,276
Okay, on one form in an app I'm building, I'm getting notifications that records are showing #DELETED# in all fields after a data change.

I've narrowed down the cause to the form being based on a SQL Server view, and the specific data change immediately causing the record to be filtered out by the view, which Access interprets as being deleted.

My original fix was to replace the view with a query, but the form's performance becomes unacceptably sluggish (which was the reason for the view in the first place). When based on the view, performance is quick and instantaneous, while when based on a query, the form populates around 2 lines per second, with 12 lines to fill in, and it re-does the entire population every time you scroll up or down.

One solution I found was to change to using an ADODB connection instead, but while the view is updateable, I cannot got the connection to be updateable. No matter what I do, it is always non-updateable.

Yes, the view contains the a designated primary key, which is the PK of the primary table it's based on. There are two fields total from other tables, but none of those may be changed by the user. One (called RecoveryName) is displayed and is a business requirement in the form, and the other two are passed to the front end to allow users to filter by whomever the records are assigned to for processing.

Sorry I can't post a screen shot, but I'd have to edit so much out that it would be completely unhelpful. Basically, you have Recovery Name, Contract, Member first and last names, record status (a drop down with around a dozen different options), and a bunch of dates.

The code below opens up an ADODB recordset just fine - I just can't seem to make it updateable.
Code:
Private Sub UpdateRecordset()

'FINDME
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset

Dim WhereClause As String
Dim SQL As String

'    If Me.RecordSource = "" Then
'        Me.RecordSource = "qryMembershipConfirmationData"
'    Else
'        Me.Requery
'    End If
    
    'Apply filter to ProcessorID if required.
    If Me.cboProcessorID.Value <> "(ALL)" Then
        WhereClause = " WHERE ProcessorBadgeID = '" & Me.cboProcessorID.Value & "'"
    End If

    'Apply filter to RecoveryID if required.
    If Me.cboRecoveryLookup.Value <> -1 Then
        If WhereClause = "" Then
            WhereClause = " WHERE "
        Else
            WhereClause = WhereClause & " AND "
        End If
        WhereClause = WhereClause & "RecoveryID = " & Me.cboRecoveryLookup.Value

        'Add additional restrictions if the form was opened by the UWS and has an OpenArg.
        If Nz(Me.OpenArgs, "") <> "" Then
            WhereClause = WhereClause & " AND DateDiff('d', MembershipChangeSubmitted, Date()) >= 14"
        End If
    End If

'    If Not rs Is Nothing Then
'        rs.Close
'        Set rs = Nothing
'    End If
'
'    If Not cn Is Nothing Then
'        cn.Close
'        Set cn = Nothing
'    End If

    SQL = "SELECT * FROM VW_MembershipConfirmationData" & " " & Trim(WhereClause) & ";"

    Set cn = CurrentProject.AccessConnection
    Set rs = New ADODB.Recordset
    
    With rs
'        Set .ActiveConnection = cn
'        cn.Mode = adModeReadWrite
'        .Source = "SELECT * FROM VW_MembershipConfirmationData" & " " & Trim(WhereClause) & ";"
        .LockType = adLockOptimistic
        .CursorType = adOpenKeyset
    End With
    
    rs.Open SQL, cn
    
    Set Me.Recordset = rs
    Set rs = Nothing
    Set cn = Nothing
    
'    Me.RecordSource = "SELECT * FROM VW_MembershipConfirmationData" & " " & Trim(WhereClause) & ";"
    
End Sub

The commented code is from my various attempts at making this work correctly.

As I said, this opens a recordset perfectly fine, and the performance as the form is navigated is perfect, but I just cannot get this to result in an UPDATEABLE recordset.

If anyone can help me with this, I'll owe you an Olde Frothingslosh.
 

CJ_London

Super Moderator
Staff member
Local time
Today, 09:34
Joined
Feb 19, 2013
Messages
16,607
I have seen this behaviour before (quite some time ago) and if I remember correctly, there was an error in the data. It wasn't apparent unless you happened to come across the incorrect data whilst scrolling or applied a filter or sort.

Looks like your code is applying a filter (rather than modify the criteria) so suggest check your data.
 

Frothingslosh

Premier Pale Stale Ale
Local time
Today, 04:34
Joined
Oct 17, 2012
Messages
3,276
I have seen this behaviour before (quite some time ago) and if I remember correctly, there was an error in the data. It wasn't apparent unless you happened to come across the incorrect data whilst scrolling or applied a filter or sort.

Looks like your code is applying a filter (rather than modify the criteria) so suggest check your data.

Actually, I'm calling it a filter in the comments, but it's generating the entire SQL statement at runtime based on user actions. The RecoveryID and ProcessorID comboboxes are unbound controls in the header, and changing their values triggers the UpdateRecordset procedure to run again.

I don't use an actual filter because there are a number of actions available to the user once they've generated the recordset they want, and they need to use the same recordset, making filters a PITA to use.

Thanks for the tip, though - the test recordset is 4 items based on real data, so verifying it tomorrow morning shouldn't take long.
 

Frothingslosh

Premier Pale Stale Ale
Local time
Today, 04:34
Joined
Oct 17, 2012
Messages
3,276
Okay, I went through the test data, and everything was valid. They were literally real records copied into a test recovery (basically, a recovery is a collection of insurance claims that we paid that we are checking to see if Medicare should have paid instead), and there were no data errors. The view itself is updateable, including the test records.

The issue was caused because the data change in question ran hard against a condition in the view's WHERE clause. This results in SQL Server immediately removing the record in question from the submitted recordset, as it no longer qualified, and Access read that as a deletion.

I never was able to make the ADO connection updateable, so instead I came up with a workaround: I removed the condition in question from the WHERE clause and instead put it into a SELECT * query against the view. That way, the record isn't removed from the view immediately upon saving, so Access doesn't decide that it got deleted.

It didn't fix the ADO problem, but it absolutely fixed the #DELETED# problem while avoiding the huge performance hit other front-end solutions created, so I'm calling it a win.

Thanks for your help, though!
 

Users who are viewing this thread

Top Bottom