Remoting IDataAccessAdapter with Manager Templates

Posts   
 
    
GizmoTN76
User
Posts: 36
Joined: 22-Oct-2007
# Posted on: 22-Oct-2007 19:54:14   

I'm in the process of putting together a system which needs to talk to both oracle and sql server. I'm using LLBLGEN 2.5 against .net 3.0.

As I don't want to deal with the configuration, security and installation issues of letting clients talk directly to the database I would like to have this connectivity handled on a central server via a remoting interface.

I'm dealing with a developer pool which is totally unfamiliar with LLBLGEN. I love the simplicity of the self servicing model and think this would allow them to ramp up faster however the constraints of multiple databases basically rules that out.

Upon a little investigation I ran across the manager templates which seem like they would be a good answer to return that simplicity to the adapter model however I've noticed several things about that template group which appear to prevent this out of the box.

First off all the template methods are marked as static. Obviously this could be changed in the templates so that the managers were created as instances with instance methods but remoting the managers directly would still require more work such as creating interfaces they obeyed etc. It seems like this would also be a pain in that they'd have to be registered individually on the server as remoting endpoints so that might be a thorn in the side to maintain.

The second issue with the Manager templates is that they directly create DataAccessAdapters inline. IE "using( DataAccessAdapter adapter = new DataAccessAdapter() )" Obviously the templates could be modified to call a factory method which would return an IDataAccessAdapter but again I'd like the real DataAccessAdapters to live on the server.

From a programmatic standpoint it seems like it would be easiest to keep the Managers local to the client and then have them proxy their calls across a remoting boundary to a Decorator of the IDataAccessAdapter which would then talk to a factory created DataAccessAdapter. The local managers would just talk to the local IDataAccessAdapter which could call the server instance to do the heavy lifting. This would treat the adapter methods like exposed service methods allowing the most reuse for the least code on the client.

First question.... is this architecture sane? wink Has anyone tried something similar? If so did it work or is it a dead end? Has anyone got some manager templates they've already modified to do something similar?

Is there an easier approach that meet my constraints? I've been reading the forums searching for an answer for the past couple of days and drawn a blank. It seems like this would be a common problem for people who had to support multiple databases. Essentially I need something which will:

  1. Place all interaction with the real DataAccessAdapters on the server where the DataAccessAdapters can be either Oracle or Sql Server.
  2. Offer the simplicity of the manager templates/Self Servicing.
  3. Avoid registering potentially 100s of managers as remoting interface endpoints.

Any help, suggestions, code/template samples would be greatly appreciated.

Rogelio
User
Posts: 221
Joined: 29-Mar-2005
# Posted on: 26-Oct-2007 13:28:19   

Hi,

I can give my implementation with the adapter model, do you want it?

GizmoTN76
User
Posts: 36
Joined: 22-Oct-2007
# Posted on: 26-Oct-2007 13:45:26   

Rogelio wrote:

Hi,

I can give my implementation with the adapter model, do you want it?

Absolutely! simple_smile I've been context switching to some other tasks so I haven't gotten around to implementing it yet and I'm sure you've probably jumped over some hurdles I'm going to run into. I've modified the manager templates to create their own project and was getting ready to put in a factory implementation for the adapter so they can call off to a proxy adapter clientside which in turn calls the server one so that would be great if you've already crossed that bridge.

Thanks!

Scott

Angus
User
Posts: 44
Joined: 08-Jul-2005
# Posted on: 26-Oct-2007 16:33:58   

Rogelio wrote:

Hi,

I can give my implementation with the adapter model, do you want it?

Rogelio, I too would be interested in taking a look at your implementation. I have a similar situation that I am addressing and welcome any ideas on how to create a better / more flexible architecture.

Thanks

Chris smile

Rogelio
User
Posts: 221
Joined: 29-Mar-2005
# Posted on: 27-Oct-2007 19:27:03   

GizmoTN76 wrote:

Absolutely! simple_smile I've been context switching to some other tasks so I haven't gotten around to implementing it yet and I'm sure you've probably jumped over some hurdles I'm going to run into. I've modified the manager templates to create their own project and was getting ready to put in a factory implementation for the adapter so they can call off to a proxy adapter clientside which in turn calls the server one so that would be great if you've already crossed that bridge.

Thanks!

Scott

Ok,

First the interface assembly:



<Serializable()> _
Public Class DataServerInfo
    Implements ICloneable

    Public SqlServer As String
    Public Database As String
    Public UserID As String
    Public CultureName As String
    .....   

    Public Function Clone() As Object Implements System.ICloneable.Clone

        Dim info As DataServerInfo
        info = Me.MemberwiseClone

        Return info
    End Function
End Class

The DataServerInfo class allows to use the same remote business objects
to access differences database (with the same structure, for example when
you have each one database for each branch. Normally people prefer to have
only one database with all branches data; but when you want performance
it is better to have one database per branch).


Public Enum ServiceMode 
    Local = 0
    Remoting = 1
    WebServices = 2
    ......
End Enum

This enumeration is for the kind of business objects that you want yo use.
At this moment I only work with local and remoting.



Public Interface IBasicBusiness

    Function GetByPK(ByVal pk() As Object, ByVal serverInfo As DataServerInfo) As ORMSupportClasses.EntityBase2
    Function GetByID(ByVal id() As Object, ByVal serverInfo As DataServerInfo) As ORMSupportClasses.EntityBase2
    Function Update(ByVal entity As ORMSupportClasses.EntityBase2, ByVal serverInfo As DataServerInfo) As Object
    Sub Delete(ByVal pk() As Object, ByVal serverInfo As DataServerInfo)
    ......

End Interface

This interface contains the basic methods that must be implemented by each
business class, I have not migrated it to generic yet.


Public Interface IBusinessFactory

    Function GetCustomerBusiness() As Interfaces.ICustomerBusiness
    .....

End Interface

This interface contains the functions that must be implemented by all 
the factories (LocalServices, RemotingServices, etc)  that return business object


Public Interface ICustomerBusiness
    Inherits IBasicBusiness

End Interface

This interface is an example of interface for a business class (in this case Customer)



The business assembly:



Public MustInherit Class BasicBusiness
    Inherits MarshalByRefObject
    Implements Interfaces.IBasicBusiness, ....

    Protected errorDelete As String
    Protected recordDB As DataAccess.BasicDB  ' this keep the data access object for Customer

    ' config the object to stay alive forever during remoting
    Public Overrides Function InitializeLifetimeService() As Object
        MyBase.InitializeLifetimeService()
        Return Nothing
    End Function

    Public Overridable Sub Delete(ByVal pk() As Object, ByVal serverInfo As Interfaces.DataServerInfo) Implements Interfaces.IBasicBusiness.Delete

        Try
            ' try to delete the record
            Me.recordDB.Delete(pk, serverInfo, Nothing)

        Catch ex As MyCustomAppException
            Throw
        Catch ex As Exception
            Throw New MyCustomAppException(Me.errorDelete, ex)
        End Try

    End Sub

    Public Overridable Function GetByID(ByVal id() As Object, ByVal serverInfo As Interfaces.DataServerInfo) As ORM.EntityBase2 Implements Interfaces.IBasicBusiness.GetByID

        Dim entity As ORM.EntityBase2 = Me.recordDB.GetByID(id, serverInfo, Nothing)

        Return entity
    End Function

    Public Overridable Function GetByPK(ByVal pk() As Object, ByVal serverInfo As Interfaces.DataServerInfo) As ORM.EntityBase2 Implements Interfaces.IBasicBusiness.GetByPK

        Dim entity As ORM.EntityBase2 = Me.recordDB.GetByPK(pk, serverInfo, Nothing)
        Return entity
    End Function

    Public Overridable Function Update(ByVal entity As ORM.EntityBase2, ByVal serverInfo As Interfaces.DataServerInfo) Implements Interfaces.IBasicBusiness.Update
        Return Me.recordDB.Update(entity, serverInfo, False, Nothing)
    End Function

  ........
End Class

This class implements the basic business interface , all the business classes will
inherit from this.  Most methods are overridable to be allow overrides them in the specific business class.



Public Class CustomerBusiness
    Inherits BasicBusiness
    Implements ICustomerBusiness

    Private Shared _instance As New CustomerBusiness

    ' singleton pattern
    Public Shared ReadOnly Property Instance() As CustomerBusiness
        Get
            Return _instance
        End Get
    End Property


    Private Sub New()
        MyBase.New()

        Me.errorDelete = "Error message when the customer could not be deleted"
        Me.recordDB = DataAccess.UserDB.Instance
    End Sub
End Class


The Data access assembly:



Imports ORM = SD.LLBLGen.Pro.ORMSupportClasses
Imports DH = .....HelperClasses
Imports DI = ........DataLibrary

Public MustInherit Class BasicDB

    Protected errorRead As String
    Protected errorUpdate As String

     Protected MustOverride Function GetNewEntityPK(ByVal pk() As Object) As ORM.EntityBase2

     Protected MustOverride Function GetNewEntityFactory() As ORM.IEntityFactory2

     Protected MustOverride Sub ConfigBucketByID(ByVal id() As Object, ByVal bucket As ORM.RelationPredicateBucket)


    Public Overridable Function GetByID(ByVal id() As Object, ByVal serverInfo As Interfaces.DataServerInfo, _
                                        ByVal adapter As ORM.DataAccessAdapterBase) As ORM.EntityBase2

        Dim bucket As New ORM.RelationPredicateBucket
        Dim entities As DH.EntityCollection

        Try

            entities = New DH.EntityCollection(Me.GetNewEntityFactory)
            Me.ConfigBucketByID(id, bucket)

            Me.FillCollection(entities, bucket, serverInfo, adapter)

            If entities.Count > 0 Then
                Return entities(0)
            Else
                Return Nothing
            End If

        Catch ex As MyCustomAppException
            Throw

        Catch ex As Exception
            Throw New MyCustomAppException(Me.errorRead, ex)
        End Try
    End Function

       Public Overridable Function GetByPK(ByVal pk() As Object, ByVal serverInfo As Interfaces.DataServerInfo, _
                                        ByVal adapter As ORM.DataAccessAdapterBase) As ORM.EntityBase2

        Dim entity As ORM.EntityBase2

        Try

            entity = Me.GetNewEntityPK(pk)

            Me.FetchEntity(entity, serverInfo, adapter)

            If entity.Fields.State = ORM.EntityState.Fetched Then
                Return entity
            Else
                Return Nothing
            End If

        Catch ex As MyCustomAppException
            Throw

        Catch ex As Exception
            Throw New MyCustomAppException(Me.errorRead, ex)
        End Try

    End Function

    Protected Sub FetchEntity(ByVal entity As ORM.EntityBase2, ByVal serverInfo As Interfaces.DataServerInfo, ByVal adapter As ORM.DataAccessAdapterBase)

        Dim newAdapter As Boolean = False

        Try

            If adapter Is Nothing Then
                adapter = DataSetSupport.GetNewDataAdapter(serverInfo, False)
                newAdapter = True
            End If

            adapter.FetchEntity(entity)

        Catch ex As  MyCustomAppException
            Throw

        Catch ex As Exception
            Throw New  MyCustomAppException(Me.errorRead, ex)
        Finally
            If newAdapter AndAlso Not adapter Is Nothing Then
                adapter.Dispose()
            End If
        End Try

    End Sub

.....

End Class

This class implements the basic data access functions. All the data access classes
inherit from it.


Public Class CustomerDB
    Inherits BasicDB

    ' singelton pattern
    Public Shared ReadOnly Instance As New CustomerDB


    Private Sub New()
        Me.errorRead = ......
        Me.errorUpdate = .........
    End Sub


    Protected Overrides Sub ConfigBucketByID(ByVal id() As Object, ByVal bucket As ORM.RelationPredicateBucket)
        bucket.PredicateExpression.Add(DF.PredicateFactory.CompareValue(DataLibrary.CustomerFieldIndex.CustomerId, ORM.ComparisonOperator.Equal, id(0)))
    End Sub


    Protected Overrides Function GetNewEntityPK(ByVal pk() As Object) As SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2
        Dim entity As New DataLibrary.EntityClasses.CustomerEntity
        entity.CustomerPk = pk(0)
        Return entity
    End Function

    Protected Overrides Function GetNewEntityFactory() As ORM.IEntityFactory2
        Return New DataLibrary.FactoryClasses.CustomerEntityFactory
    End Function

End Class

This class is an example of a data access class.


The business factory assembly:



Public NotInheritable Class BusinessFactory

    Private Sub New()
    End Sub

    Private Shared _factory As IBusinessFactory

    ' to get the default business factory
    Public Shared Function GetBusinessFactory() As Interfaces.IBusinessFactory
        Return _factory
    End Function

    ' this method allow to get a business factory that is not the default
    Public Shared Function GetBusinessFactory(ByVal mode As Interfaces.ServiceMode) As Interfaces.IBusinessFactory

        Select Case mode

            Case Interfaces.ServiceMode.Local
                Return LocalServices.Instance

            Case Interfaces.ServiceMode.Remoting
                Return RemotingServices.Instance

            Case Interfaces.ServiceMode.WebServices
               ' Return WebServices.Instance

        End Select
    End Function

    ' to config the default business factory
    Public Shared Sub ReadConfig()

        Dim serviceMode As String
        Dim _serviceMode As Interfaces.ServiceMode

        serviceMode = System.Configuration.ConfigurationSettings.AppSettings("BusinessServiceMode")

         If Not serviceMode Is Nothing Then
            Select Case serviceMode.ToLower
                Case "local"
                    _serviceMode = ServiceMode.Local
                Case "remoting"
                    _serviceMode = ServiceMode.Remoting
                Case "webservices"
                    _serviceMode = ServiceMode.WebServices
                Case Else
                    _serviceMode = ServiceMode.Local
            End Select
        End If

        _factory = GetBusinessFactory(_serviceMode)
    End Sub


End Class

The businessFactory class is used to get factories that can return business object (the returned business objects can be local, remote, etc)



Friend Class RemotingServices
    Implements Interfaces.IBusinessFactory

    ' singleton pattern
    Public Shared ReadOnly Instance As New RemotingServices

    Private Sub New()
        Me._remoteServicesFactory = New Services.Remoting.RemoteServicesFactory
    End Sub

    Private _remoteServicesFactory As Services.Remoting.RemoteServicesFactory

    Private ReadOnly Property RemoteServiceFactory() As Services.Remoting.RemoteServicesFactory
        Get
            Return Me._remoteServicesFactory
        End Get
    End Property

    Private iCustomerBusiness As Interfaces.ICustomerBusiness

    Public Function GetCustomerBusiness() As Interfaces.ICustomerBusiness Implements Interfaces.IBusinessFactory.GetCustomerBusiness

        If Me.iCustomerBusiness Is Nothing Then
            Me.iCustomerBusiness = Me.RemoteServiceFactory.GetSCustomerBusiness
        End If

        Return Me.iCustomerBusiness 
    End Function

End Class

Friend Class LocalServices
    Implements Interfaces.IBusinessFactory

    
    Private Sub New()
    End Sub

    Public Shared ReadOnly Instance As New LocalServices

    Public Function GetCustomerBusiness() As Interfaces.ICustomerBusiness Implements Interfaces.IBusinessFactory.GetCustomerBusiness
        Return CustomerBusiness.Instance
    End Function

End Class

As you can see the LocalServices and RemotingServices implement IBusinessFactory, this allow to work with any instance of this classes as the IBusinessFactory.


The RemotingServices assembly. The RemoteServicesFactory class is used to get the business objects via Remoting, this is the only class that you need to register, with remoting, at the server and at the client, this is the only class in the assembly.



Public Class RemoteServicesFactory
    Inherits MarshalByRefObject
    Implements Interfaces.IBusinessFactory

    ' config the object to stay alive forever during remoting
    Public Overrides Function InitializeLifetimeService() As Object
        MyBase.InitializeLifetimeService()
        Return Nothing
    End Function

    Public Function GetCustomerBusiness() As Interfaces.ISucursalCustomerBusiness Implements Interfaces.IBusinessFactory.GetCustomerBusiness
        Return CustomerBusiness.Instance
    End Function

.........

End Class


The UI assembly:



To register your remote object factory:
   RemotingConfiguration.Configure("MyApp.exe.config")



Your MyApp.exe.config:

<appSettings file="user.config">
       <add key="BusinessServiceMode" value="Local"/>
  ........
</appSettings>

<system.runtime.remoting>
   <application name="MyAppClient">
      <client>
        <wellknown type="MyNameSpace.Remoting.RemoteServicesFactory, MyRemotingServicesAssembly" url="tcp://MyServer:MyPort/MyServer/RemoteServicesFactory" />

      </client>
      <channels>
         <channel ref="tcp client">
            <serverProviders>
               <formatter ref="binary" typeFilterLevel="Full" />
            </serverProviders>
         </channel>
      </channels>
   </application>
</system.runtime.remoting>



In you main form to config the default business factory:
    BusinessFactory.ReadConfig()


When you want a customer business object:

   Dim customerBS as ICustomerBusiness
   customerBS = BusinessFactory.GetBusinessFactory().GetSucursalBusiness

As you can see your code do not know nothing about the source of your business objects, your customer business can be a local object or a remote object, all depend of your app configuration.  At any time you can be using remote and local business objects at the same time.


The configuration at the server:



<system.runtime.remoting>
   <application name="MyAppServer">
      <service>
         <wellknown mode="Singleton" 
                               type="MyNameSpace.Remoting.RemoteServicesFactory, MyRemotingServicesAssembly" 
                           objectUri="RemoteServicesFactory" />
      </service>
      <channels>
         <channel ref="tcp server" port="MyPort">
            <serverProviders>
               <formatter ref="binary" typeFilterLevel="Full" />
           </serverProviders>
         </channel>
     </channels>
   </application>
   <customErrors mode="off" />
</system.runtime.remoting>



If you need additional details let me know.

GizmoTN76
User
Posts: 36
Joined: 22-Oct-2007
# Posted on: 28-Oct-2007 18:28:37   

Thanks so much! It's been a few years since I've done vb.net so I went ahead and did a c# conversion so I could study in my native tongue simple_smile . I'm going to go ahead and post that conversion for the benefit of others. I really appreciate the effort you put into that post.



[Serializable()] 
public class DataServerInfo : ICloneable 
{ 
    
    public string SqlServer; 
    public string Database; 
    public string UserID; 
    public string CultureName; 
    
    public object System.ICloneable.Clone() 
    { 
        
        DataServerInfo info; 
        info = this.MemberwiseClone; 
        
        return info; 
    } 
} 


public enum ServiceMode 
{ 
    Local = 0, 
    Remoting = 1, 
    WebServices = 2 
} 

public interface IBasicBusiness 
{ 
    
    ORMSupportClasses.EntityBase2 GetByPK(object[] pk, DataServerInfo serverInfo); 
    ORMSupportClasses.EntityBase2 GetByID(object[] id, DataServerInfo serverInfo); 
    object Update(ORMSupportClasses.EntityBase2 entity, DataServerInfo serverInfo); 
    void Delete(object[] pk, DataServerInfo serverInfo); 
    
} 


public interface IBusinessFactory 
{ 
    Interfaces.IUserBusiness GetUserBusiness(); 
} 

public interface ICustomerBusiness : IBasicBusiness 
{ 
    
} 

public abstract class BasicBusiness : MarshalByRefObject, Interfaces.IBasicBusiness {
    
    protected string errorDelete;
    
    protected DataAccess.BasicDB recordDB;
    
    //  this keep the data access object for Customer
    //  config the object to stay alive forever during remoting
    public override object InitializeLifetimeService() {
        base.InitializeLifetimeService();
        return null;
    }
    
    public virtual void Delete(object[] pk, Interfaces.DataServerInfo serverInfo) {
        try {
            //  try to delete the record
            this.recordDB.Delete(pk, serverInfo, null);
        }
        catch (MyCustomAppException ex) {
            throw;
        }
        catch (Exception ex) {
            throw new MyCustomAppException(this.errorDelete, ex);
        }
    }
    
    public virtual ORM.EntityBase2 GetByID(object[] id, Interfaces.DataServerInfo serverInfo) {
        ORM.EntityBase2 entity = this.recordDB.GetByID(id, serverInfo, null);
        return entity;
    }
    
    public virtual ORM.EntityBase2 GetByPK(object[] pk, Interfaces.DataServerInfo serverInfo) {
        ORM.EntityBase2 entity = this.recordDB.GetByPK(pk, serverInfo, null);
        return entity;
    }
    
    public virtual void Update(ORM.EntityBase2 entity, Interfaces.DataServerInfo serverInfo) {
        return this.recordDB.Update(entity, serverInfo, false, null);
    }
}

public class CustomerBusiness : BasicBusiness, ICustomerBusiness {
    
    private static CustomerBusiness _instance = new CustomerBusiness();
    
    private CustomerBusiness() {
        this.errorDelete = "Error message when the customer could not be deleted";
        this.recordDB = DataAccess.UserDB.Instance;
    }
    
    //  singleton pattern
    public static CustomerBusiness Instance {
        get {
            return _instance;
        }
    }
}



public abstract class BasicDB 
{ 
    
    protected string errorRead; 
    protected string errorUpdate; 
    
    protected abstract ORM.EntityBase2 GetNewEntityPK(object[] pk); 
    
    protected abstract ORM.IEntityFactory2 GetNewEntityFactory(); 
    
    protected abstract void ConfigBucketByID(object[] id, ORM.RelationPredicateBucket bucket); 
    
    
    public virtual ORM.EntityBase2 GetByID(object[] id, Interfaces.DataServerInfo serverInfo, ORM.DataAccessAdapterBase adapter) 
    { 
        
        ORM.RelationPredicateBucket bucket = new ORM.RelationPredicateBucket(); 
        DH.EntityCollection entities; 
        
        try { 
            
            entities = new DH.EntityCollection(this.GetNewEntityFactory); 
            this.ConfigBucketByID(id, bucket); 
            
            this.FillCollection(entities, bucket, serverInfo, adapter); 
            
            if (entities.Count > 0) { 
                return entities(0); 
            } 
            else { 
                return null; 
            } 
        } 
        
        catch (MyCustomAppException ex) { 
            throw; 
        } 
        
        catch (Exception ex) { 
            throw new MyCustomAppException(this.errorRead, ex); 
        } 
    } 
    
    public virtual ORM.EntityBase2 GetByPK(object[] pk, Interfaces.DataServerInfo serverInfo, ORM.DataAccessAdapterBase adapter) 
    { 
        
        ORM.EntityBase2 entity; 
        
        try { 
            
            entity = this.GetNewEntityPK(pk); 
            
            this.FetchEntity(entity, serverInfo, adapter); 
            
            if (entity.Fields.State == ORM.EntityState.Fetched) { 
                return entity; 
            } 
            else { 
                return null; 
            } 
        } 
        
        catch (MyCustomAppException ex) { 
            throw; 
        } 
        
        catch (Exception ex) { 
            throw new MyCustomAppException(this.errorRead, ex); 
        } 
        
    } 
    
    protected void FetchEntity(ORM.EntityBase2 entity, Interfaces.DataServerInfo serverInfo, ORM.DataAccessAdapterBase adapter) 
    { 
        
        bool newAdapter = false; 
        
        try { 
            
            if (adapter == null) { 
                adapter = DataSetSupport.GetNewDataAdapter(serverInfo, false); 
                newAdapter = true; 
            } 
            
            adapter.FetchEntity(entity); 
        } 
        
        catch (MyCustomAppException ex) { 
            throw; 
        } 
        
        catch (Exception ex) { 
            throw new MyCustomAppException(this.errorRead, ex); 
        } 
        finally { 
            if (newAdapter && (adapter != null)) { 
                adapter.Dispose(); 
            } 
        } 
        
    } 
    
} 


public class CustomerDB : BasicDB {
    
    private CustomerDB Instance = new CustomerDB();
    
    private CustomerDB() {
    }
    
    protected override void ConfigBucketByID(object[] id, ORM.RelationPredicateBucket bucket) {
        bucket.PredicateExpression.Add(DF.PredicateFactory.CompareValue(DataLibrary.CustomerFieldIndex.CustomerId, ORM.ComparisonOperator.Equal, id(0)));
    }
    
    protected override SD.LLBLGen.Pro.ORMSupportClasses.EntityBase2 GetNewEntityPK(object[] pk) {
        DataLibrary.EntityClasses.CustomerEntity entity = new DataLibrary.EntityClasses.CustomerEntity();
        entity.CustomerPk = pk(0);
        return entity;
    }
    
    protected override ORM.IEntityFactory2 GetNewEntityFactory() {
        return new DataLibrary.FactoryClasses.CustomerEntityFactory();
    }
}


public sealed class BusinessFactory {
    
    private static IBusinessFactory _factory;
    
    private BusinessFactory() {
    }
    
    //  to get the default business factory
    public static Interfaces.IBusinessFactory GetBusinessFactory() {
        return _factory;
    }
    
    //  this method allow to get a business factory that is not the default
    public static Interfaces.IBusinessFactory GetBusinessFactory(Interfaces.ServiceMode mode) {
        switch (mode) {
            case Interfaces.ServiceMode.Local:
                return LocalServices.Instance;
                break;
            case Interfaces.ServiceMode.Remoting:
                return RemotingServices.Instance;
                break;
            case Interfaces.ServiceMode.WebServices:
                //  Return WebServices.Instance
                break;
        }
    }
    
    //  to config the default business factory
    public static void ReadConfig() {
        string serviceMode;
        Interfaces.ServiceMode _serviceMode;
        serviceMode = System.Configuration.ConfigurationSettings.AppSettings("BusinessServiceMode");
        if (!(serviceMode == null)) {
            switch (serviceMode.ToLower) {
                case "local":
                    _serviceMode = ServiceMode.Local;
                    break;
                case "remoting":
                    _serviceMode = ServiceMode.Remoting;
                    break;
                case "webservices":
                    _serviceMode = ServiceMode.WebServices;
                    break;
                default:
                    _serviceMode = ServiceMode.Local;
                    break;
            }
        }
        _factory = GetBusinessFactory(_serviceMode);
    }
}

class RemotingServices : Interfaces.IBusinessFactory {
    
    private RemotingServices Instance = new RemotingServices();
    
    private Services.Remoting.RemoteServicesFactory _remoteServicesFactory;
    
    private Interfaces.ICustomerBusiness iCustomerBusiness;
    
    private RemotingServices() {
        this._remoteServicesFactory = new Services.Remoting.RemoteServicesFactory();
    }
    
    private Services.Remoting.RemoteServicesFactory RemoteServiceFactory {
        get {
            return this._remoteServicesFactory;
        }
    }
    
    public Interfaces.ICustomerBusiness GetCustomerBusiness() {
        if ((this.iCustomerBusiness == null)) {
            this.iCustomerBusiness = this.RemoteServiceFactory.GetSCustomerBusiness;
        }
        return this.iCustomerBusiness;
    }
}

public class RemoteServicesFactory : MarshalByRefObject, Interfaces.IBusinessFactory {
    
    //  config the object to stay alive forever during remoting
    public override object InitializeLifetimeService() {
        base.InitializeLifetimeService();
        return null;
    }
    
    public Interfaces.ISucursalCustomerBusiness GetCustomerBusiness() {
        return CustomerBusiness.Instance;
    }
}




class LocalServices : Interfaces.IBusinessFactory {
    
    private LocalServices Instance = new LocalServices();
    
    private LocalServices() {
    }
    
    public Interfaces.ICustomerBusiness GetCustomerBusiness() {
        return CustomerBusiness.Instance;
    }
}



GizmoTN76
User
Posts: 36
Joined: 22-Oct-2007
# Posted on: 28-Oct-2007 21:55:50   

Rogelio, it looks like a pretty clean design in how you separated the layers out. Did you hand code the custom stuff per entity or did you use a template/code generator to handle it? It looks alot of the entity specific stuff could be done with templates, just curious if you were already.

Rogelio
User
Posts: 221
Joined: 29-Mar-2005
# Posted on: 30-Oct-2007 13:38:01   

GizmoTN76 wrote:

Rogelio, it looks like a pretty clean design in how you separated the layers out. Did you hand code the custom stuff per entity or did you use a template/code generator to handle it? It looks alot of the entity specific stuff could be done with templates, just curious if you were already.

I hand code the custom stuff. If you develop the template then let me know.