8128
8128

Reputation: 999

Design pattern for object deletion?

Suppose I have an object that is stored in a database (in my example below, of the class Aggregation). If I want to be able to delete it, running .Delete() seems like the obvious way to go.

When this method is called, my current approach is to delete it from the database, and then in the code that calls it, destroy the object. However this feels wrong - what happens if the code that calls it doesn't actually destroy the object. Then all sorts of inconsistencies could happen.

One route would be to set a flag when .Delete() is called, and then check this flag before running any other function or subroutine. But is there a prettier way?

Sorry for asking this question - I feel it should be more obvious, but Googling hasn't helped.

Imports System.Data.SqlClient

Public Class Aggregation

    Public ReadOnly Property ID As Integer
    Public ReadOnly Property Name As String

    Private Sub New(ID As Integer, name As String)
        Me.ID = ID
        Me.Name = name
    End Sub

    Public Shared Function CreateNew(Name As String) As Aggregation
        Dim query As String = "INSERT INTO TRAF_AGGREGATION (NAME) VALUES (@NAME); SELECT SCOPE_IDENTITY();"
        Using cmd As New SqlCommand(query)
            cmd.Parameters.AddWithValue("@NAME", Name)

            Dim result As DataTable = Core._dm.ExecuteQuery(cmd)
            Return New Aggregation(result.Rows(0).Item(0), Name)
        End Using
    End Function

    Public Shared Function Load(AggregationID As Integer) As Aggregation
        Dim query As String = "SELECT * FROM AGGREGATION WHERE ID = @ID;"
        Using cmd As New SqlCommand(query)
            cmd.Parameters.AddWithValue("@ID", AggregationID)
            Dim result As DataTable = Core._dm.ExecuteQuery(cmd)
            If result.Rows.Count = 0 Then
                Throw New ArgumentOutOfRangeException("AggregationID", AggregationID, "No aggregation with this ID")
            Else
                Return New Aggregation(AggregationID, result(0)("NAME"))
            End If
        End Using
    End Function

    Friend Sub Rename(newName As String)
         ...
    End Sub

    ....

    Friend Sub Delete()
        Dim query As String = "DELETE FROM AGGREGATION WHERE ID = @ID;"
        Using cmd As New SqlCommand(query)
            cmd.Parameters.AddWithValue("@ID", ID)
            Core._dm.ExecuteNonQuery(cmd)
        End Using
        _ID = -1
    End Sub
End Class

Upvotes: 1

Views: 625

Answers (1)

Andrea Rega
Andrea Rega

Reputation: 371

As Alex B. suggests, the best solution is to use an ORM that handles all this complexity for you.

But if you don't or you cannot use it, i think that a better approach could be:

  1. Remove all the CRUD method from your Entity class (Aggregation)
  2. Define a sort of Controller that implements the CRUD methods onto your entity class and that returns appropriate result events/objects
  3. Define a sort of ConnectionFactory that will handle the connection towards the database and will manage the various sessions
  4. Define an EntityMapper that will map the query result into your Entity and vice-versa
  5. Define a QueryUtils that will handle all the low level sql syntax and criteria building in a reusable way

Going back to your question, the point is the order in which you execute the actions:

  1. at first you execute the query, the object (or driver) that performs this action will return a result or an exception
  2. you handle the result or the exception
  3. if all went ok then you can update the entity state or remove from the application context

Hope this could help you!

Upvotes: 1

Related Questions