Telerik OpenAccess Classic

Telerik OpenAccess ORM Send comments on this topic.
How to: Deal with interfaces
Programmer's Guide > OpenAccess ORM Classic (Old API) > OpenAccess Tasks > Defining a Data Model > How to: Deal with interfaces

Glossary Item Box

This documentation article is a legacy resource describing the functionality of the deprecated OpenAccess Classic only. The contemporary documentation of Telerik OpenAccess ORM is available here.

In many cases it is helpful to separate information access into an interface. OpenAccess provides the functionality to make interfaces persistent. In contrast to a normal persistent class, an interface contains no fields. Potentially the interface hierarchy and the class inheritance hierarchy are not perfect matches, and an interface could also be implemented by many persistent class hierarchies. This makes the use of interfaces ambiguous wrt. Class-table mapping and therefore certain restrictions apply; e.g. it is not possible to include query arguments from an interface in an OQL Query.

Datastore identity, default HIGHLOW key generator

We have a class Address with a reference to an interface ICity. The implementation of this interface is in the class ACity.

The interface is marked as persistent although it cannot define any fields.
C# Copy Code
[Persistent]
public interface ICity {
   
string CityName {
       get;
       set;
   }
}
[Persistent]
public class ACity : ICity {
   
private string acity;
   
public string CityName {
       get {
return acity; }
       set { acity = value; }
   }
}
[Persistent]
public class Address {
   
private ICity iCity;
   
public ICity ICityProperty {
       get {
return iCity; }
       set { iCity = value; }
   }
}  
VB.NET Copy Code
<Persistent()> _
Public Interface ICity
    Property CityName() As String
End Interface
<Persistent()> _
Public Class ACity
    Implements ICity
    Private acity As String
    Public Property CityName() As String
        Get
            Return acity
        End Get
        Set
            acity = value
        End Set
    End Property
End Class
<Persistent()> _
Public Class Address
    Private iCity As ICity
    Public Property ICityProperty() As ICity
        Get
            Return iCity
        End Get
        Set
            iCity = value
        End Set
    End Property
End Class

The corresponding app.config will not need any additional entries. The default mapping information, present in the app.config file is used.

Datastore identity, HIGHLOW key generator

We advance the model with a second interface that is also declared as persistent:

C# Copy Code
[Persistent]
public interface ICity {
   
string CityName {
       get;
       set;
   }
}
[Persistent]
public interface IStreet {
   
string StreetName {
       get;
       set;
   }
}
[Persistent]
public class ACity : ICity, IStreet{
   
private string acity;
   
private string astreet;
   
public string CityName {
       get {
return acity; }
       set { acity = value; }
   }

   
public string StreetName {
       get {
return astreet;}
       set { astreet = value;}
   }
}
[Persistent]
public class Address {
   
private ICity iCity;
   
private IStreet iStreet;
       
public IStreet IStreetProperty {
       get {
return iStreet; }
       set { iStreet = value; }
   }
   
public ICity ICityProperty {
       get {
return iCity; }
       set { iCity = value; }
   }
}  
VB.NET Copy Code
<Persistent()> _
Public Interface ICity
    Property CityName() As String
End Interface
<Persistent()> _
Public Interface IStreet
    Property StreetName() As String
End Interface
<Persistent()> _
Public Class ACity
    Implements ICity
    Implements IStreet
    Private acity As String
    Private astreet As String
    Public Property CityName() As String
        Get
            Return acity
        End Get
        Set
            acity = value
        End Set
    End Property

    Public Property StreetName() As String
        Get
            Return astreet
        End Get
        Set
            astreet = value
        End Set
    End Property
End Class
<Persistent()> _
Public Class Address
    Private iCity As ICity
    Private iStreet As IStreet
    Public Property IStreetProperty() As IStreet
        Get
            Return iStreet
        End Get
        Set
            iStreet = value
        End Set
    End Property
    Public Property ICityProperty() As ICity
        Get
            Return iCity
        End Get
        Set
            iCity = value
        End Set
    End Property
End Class

In this case the default mapping in the app.config is enough and no special entries are required.

Application identity - using Int as primary key. 

In this sample we have used application identity, and the primary keys are of int type. The only difference between this sample and Datastore identity, HIGHLOW key generator sample is the additional declaration of the identity field. Alternatively, a user defined application identity class could be used.

C# Copy Code
[Persistent]
public interface ICity {
   
string CityName {
       get;
       set;
   }
}
[Persistent]
public interface IStreet {
   
string StreetName {
       get;
       set;
   }
}
[Persistent(IdentityField = “”
public class ACity : ICity, IStreet {
   
static private int pk = 0;
   
private int acityid; // pk  
   
private string acity;
   
private string astreet;
   
public string CityName {
       get {
return acity; }
       set { acity = value; }
   }
   
public string StreetName {
       get {
return astreet; }
       set { astreet = value; }
   }

   …

[Persistent(IdentityField = “”
public class Address {
   
static private int pk = 0;
   
private int addressId; // pk  
   
private ICity iCity;
   
private IStreet iStreet;

   
public IStreet IStreetProperty {
       get {
return iStreet; }
       set { iStreet = value; }
   }

   
public ICity ICityProperty {
       get {
return iCity; }
       set { iCity = value; }
   }

   
public Address() {
       
// addressId = HelperLib.OAHelper.NextNumber();
       
addressId = pk++;
   }

   
public int AddressId {
       get {
return addressId; }
       set { addressId = value; }
   }     
}  
VB.NET Copy Code
<Persistent()> _
Public Interface ICity
    Property CityName() As String
End Interface
<Persistent()> _
Public Interface IStreet
    Property StreetName() As String
End Interface
<Persistent(IdentityField := acityid)> _
Public Class ACity
    Implements ICity
    Implements IStreet
    Private Shared pk As Integer = 0
    Private acityid As Integer
    ' pk
    Private acity As String
    Private astreet As String
    Public Property CityName() As String
        Get
            Return acity
        End Get
        Set
            acity = value
        End Set
    End Property
    Public Property StreetName() As String
        Get
            Return astreet
        End Get
        Set
            astreet = value
        End Set
    End Property

End Class

<Persistent(IdentityField := addressId)> _
Public Class Address
    Private Shared pk As Integer = 0
    Private addressId As Integer
    ' pk
    Private iCity As ICity
    Private iStreet As IStreet

    Public Property IStreetProperty() As IStreet
        Get
            Return iStreet
        End Get
        Set
            iStreet = value
        End Set
    End Property

    Public Property ICityProperty() As ICity
        Get
            Return iCity
        End Get
        Set
            iCity = value
        End Set
    End Property

    Public Sub New()
        ' addressId = HelperLib.OAHelper.NextNumber();
        addressId = System.Math.Max(System.Threading.Interlocked.Increment(pk),pk - 1)
    End Sub

    Public Property AddressId() As Integer
        Get
            Return addressId
        End Get
        Set
            addressId = value
        End Set
    End Property
End Class

Once again the app.config can stay as it is as it does not require any specific entries.

Application identity - using GUID as primary key

To be able to use Guids instead of ints as a primery key some additional information will be needed in order to get the generation tool to recognize the i_city_id and i_street_id as unique identifiers.

C# Copy Code
[Persistent]  
public interface ICity {  
   
string CityName {  
       get;  
       set;  
   }  
}  
[Persistent]  
public interface IStreet {  
   
string StreetName {  
       get;  
       set;  
   }  
}  
[Persistent(IdentityField = “”  
public class ACity : ICity, IStreet {  

   
private Guid  acityid; // pk   

   
private string acity;  
   
private string astreet;  
   
public string CityName {  
       get {
return acity; }  
       set { acity = value; }  
   }  

   
public string StreetName {  
       get {
return astreet; }  
       set { astreet = value; }  
   }  
  
   
public ACity() {  
       acityid = Guid.NewGuid();  
   }  
}  

[Persistent(IdentityField = “”  
public class Address {  
   
private Guid addressId; // pk   
   
private ICity iCity;  
   
private IStreet iStreet;  

   
public IStreet IStreetProperty {  
       get {
return iStreet; }  
       set { iStreet = value; }  
   }  

   
public ICity ICityProperty {  
       get {
return iCity; }  
       set { iCity = value; }  
   }  

   
public Address() {  
       addressId = Guid.NewGuid();  
   }  

   
public Guid AddressId {  
       get {
return addressId; }  
       set { addressId = value; }  
   }  
}   
VB.NET Copy Code
<Persistent()> _
Public Interface ICity
    Property CityName() As String
End Interface
<Persistent()> _
Public Interface IStreet
    Property StreetName() As String
End Interface
<Persistent(IdentityField := acityid)> _
Public Class ACity
    Implements ICity
    Implements IStreet

    Private acityid As Guid
    ' pk
    Private acity As String
    Private astreet As String
    Public Property CityName() As String
        Get
            Return acity
        End Get
        Set
            acity = value
        End Set
    End Property

    Public Property StreetName() As String
        Get
            Return astreet
        End Get
        Set
            astreet = value
        End Set
    End Property

    Public Sub New()
        acityid = Guid.NewGuid()
    End Sub
End Class

<Persistent(IdentityField := addressId)> _
Public Class Address
    Private addressId As Guid
    ' pk
    Private iCity As ICity
    Private iStreet As IStreet

    Public Property IStreetProperty() As IStreet
        Get
            Return iStreet
        End Get
        Set
            iStreet = value
        End Set
    End Property

    Public Property ICityProperty() As ICity
        Get
            Return iCity
        End Get
        Set
            iCity = value
        End Set
    End Property

    Public Sub New()
        addressId = Guid.NewGuid()
    End Sub

    Public Property AddressId() As Guid
        Get
            Return addressId
        End Get
        Set
            addressId = value
        End Set
    End Property
End Class

In this case the app.config entries also need to be changed, in order to explain what kind of classes we accept for the interface references:

app.config Copy Code
<mappings current="mssqlMapping">  
  
<mapping id="mssqlMapping">  
    
<namespace name="Sample4">  
      
<class name="Address">  
        
<field name="iCity">  
          
<extension key="valid-class" value="ACity" />
        
</field>
        
<field name="iStreet">  
          
<extension key="valid-class" value="ACity" />
        
</field>              
      
</class>
    
</namespace>
  
</mapping>
</mappings>  

After these changes the correct columns are generated:

Copy Code
i_city_class    int   
i_city_id       uniqueidentifier      
i_street_class  
int   
i_street_id     uniqueidentifier   
 As of now, the changes in the app.config file need to be done manually.

Application identity - using GUIDs as primary key, explicit type code

Sometimes its better to hard code the description of the class as shown in this example:

app.config Copy Code
<namespace name="Sample5">  
  
<class name="Address">  
    
<field name="iCity">  
      
<extension key="valid-class" value="ACity=ACITYCLASS" />
      
<extension key="valid-class" value="BCity=BCITYCLASS" />
    
</field>
    
<field name="iStreet">  
      
<extension key="valid-class" value="ACity=ACITYCLASS" />
    
</field>
  
</class>
</namespace>  

This makes sure that always the right class id is used and a filled database is usable, even if the class is moved or renamed. If you use the extension valid-class without the type code the automatic class id calculation at start time can fail if the target class has been renamed or moved to another namespace.