Using Csla with Inheritance and Multiple Database Engines

Using Csla with Inheritance and Multiple Database Engines

Old forum URL: forums.lhotka.net/forums/t/4819.aspx


andrewem posted on Wednesday, May 07, 2008

Hi,

Essentially, the book (VB 2005 Business Objects SE) uses a single project that contains everything: the properties (or Business Methods), Factory Methods, and Data Access. While this is great for using one database platform, we have used multiple projects to allow us to use multiple database engines. So instead of having to reproduce all of the properties and their business rules in each data project, we just inherit it in each. Although the book mentions this in a couple of lines, there are no examples. Does anyone have an example?

The reason I'm asking is because we are upgrading from 1.1 to the latest CSLA framework and the problem is that certain things conflict with the two project methodology.

For example (and this is just one example):

Public Shared Function NewWhatever() As Whatever

Return DataPortal.Create(Of Whatever)()

End Function

This does not work, because Whatever is marked as a MustInherit class and you cannot create an instance of such a class. It worked in our old methodology because the previous person who did the work tweaked the methods (i.e. never used Shared, had another factory project, etc) to get everything to work. I, on the other hand, want to take the time now to make sure that everything makes reasonable sense before we go into massively chaning large portions of code to work with the new CSLA.

Any examples that I can look at? Anyone have any ideas?

Greatly appreciated..

A

sergeyb replied on Wednesday, May 07, 2008

Disclaimer: I did not have to write a project yet against multiple databases.  However, if I had to do it, I would have tried to have a single set of business objects, and have DB specific code in data portal methods.  Moreover, I would have tried to have database factory (of sorts) that would look in config and create appropriate objects for database currently used.  Something like:  Factory.CreateConnection as DBConnection (or IDBCOnnection), etc… for other db objects.  That way your business object code is database agnostic altogether.  Just a thought…

 

 

 

Sergey Barskiy

Senior Consultant

office: 678.405.0687 | mobile: 404.388.1899

cid:_2_0648EA840648E85C001BBCB886257279
Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

 

From: andrewem [mailto:cslanet@lhotka.net]
Sent: Wednesday, May 07, 2008 1:12 PM
To: Sergey Barskiy
Subject: [CSLA .NET] Using Csla with Inheritance and Multiple Database Engines

 

Hi,

Essentially, the book (VB 2005 Business Objects SE) uses a single project that contains everything: the properties (or Business Methods), Factory Methods, and Data Access. While this is great for using one database platform, we have used multiple projects to allow us to use multiple database engines. So instead of having to reproduce all of the properties and their business rules in each data project, we just inherit it in each. Although the book mentions this in a couple of lines, there are no examples. Does anyone have an example?

The reason I'm asking is because we are upgrading from 1.1 to the latest CSLA framework and the problem is that certain things conflict with the two project methodology.

For example (and this is just one example):

Public Shared Function NewWhatever() As Whatever

Return DataPortal.Create(Of Whatever)()

End Function

This does not work, because Whatever is marked as a MustInherit class and you cannot create an instance of such a class. It worked in our old methodology because the previous person who did the work tweaked the methods (i.e. never used Shared, had another factory project, etc) to get everything to work. I, on the other hand, want to take the time now to make sure that everything makes reasonable sense before we go into massively chaning large portions of code to work with the new CSLA.

Any examples that I can look at? Anyone have any ideas?

Greatly appreciated..

A



andrewem replied on Wednesday, May 07, 2008

Does anyone else have an ideas?

One project contains the business properties etc. The other project contains the data access methods. And there is a factory layer currently that creates the objects. We have the existing methodology working perfectly. BUT, we want to develop something that closely follows the book.

My question in essence is if anyone has a rough template that shows Rocky's code and then it split up into the two projects. I can't imagine I'm the only one who uses the CSLA with multiple databases and I hope no one is going to advocate reproducing everything over and over again for each different database.

 

A

JoeFallon1 replied on Thursday, May 08, 2008

Sergey description is spot on.

I supported Oracle and SQL Server with the same CSLA BOs. I simply created a config file setting like DBType and set it to "Oracle" or SQL Server".

I have a separate Data Access Layer (DAL) which contain all the ADO.Net code and it reads the config file and creates instances of either the OracleReader or the SqlReader. (and Connection and ...). But the DAL always returns the interface IReader instead of the concrete type. Then all my BO code uses the IReader or whatever and it does not know the difference bewteen the 2 databases.

HTH

Joe

 

andrewem replied on Thursday, May 08, 2008

Hi,

I want to keep everyone up to date on my plight. I appreciate the help, but in the case above, what if I want to use a data source that doesn't conform to the Interfaces provided by .NET (for example, what if I want to use LINQ or web services to populate my class properties?)

So, I have everything set up the way I want it. I have my two assemblies (projects) with inheritance - similar to the working model we have, BUT, there is a snag: this version of the CSLA uses generics, which I like, but consider this:

DataPortal.Fetch(Of <business object>) 

The <business object> in this case is mustinherit (abstract), so the the CSLA tries to create the abstract object and of course that fails.

The old CLSA version never used inheritance, so we could create the business object using a factory and call DataPortal.Fetch and it would never create it each time (or at least in the implementation we were using that I have happened to inherit).

A

tmg4340 replied on Friday, May 09, 2008

andrewem:

Hi,

I want to keep everyone up to date on my plight. I appreciate the help, but in the case above, what if I want to use a data source that doesn't conform to the Interfaces provided by .NET (for example, what if I want to use LINQ or web services to populate my class properties?)

Then you code your DAL project to manage whatever your data sources are.  If you are supporting disparate data sources - especially if one of them is a web service - then your best bet is to probably use DTO's to transfer your data.  I responded to another thread outlining some of this (http://forums.lhotka.net/forums/thread/12631.aspx), but basically you put your DTO's into a separate assembly, and use those to transmit your data back and forth between your DAL and your BO's.

andrewem:

So, I have everything set up the way I want it. I have my two assemblies (projects) with inheritance - similar to the working model we have, BUT, there is a snag: this version of the CSLA uses generics, which I like, but consider this:

DataPortal.Fetch(Of <business object>) 

The <business object> in this case is mustinherit (abstract), so the the CSLA tries to create the abstract object and of course that fails.

The old CLSA version never used inheritance, so we could create the business object using a factory and call DataPortal.Fetch and it would never create it each time (or at least in the implementation we were using that I have happened to inherit).

You've asked this question several times in several different places, so you must not be getting the answers that you want (or any at all).  I'm not sure what you mean by "the old CSLA never used inheritance", but that's not really what's got me scratching my head.  I'm going to step back a bit and ask a different question:

Why would you want to call a DataPortal method with an abstract class?

I must not be getting it, because for the life of me I can't see how that buys you anything.  You have to cast that everywhere.  I know that you're trying not to have to re-write a bunch of existing code, but I just don't see how that design was helpful, regardless of the version of CSLA used.  IMHO, sometimes it's just better to rip off the band-aid...

- Scott

andrewem replied on Friday, May 09, 2008

Hi Scott,

Don't worry about it. I've found a solution. I have compiled a list of all the solutions that people stated on here, but many of them have problems. For example, using Interfaces such as IDBConnection doesn't work very well if you are using Web Services (for example) to obtain your data. These DTO's we were looking at seem to add a whole new level of complexity to something that for the way we were doing it originally was simple and worked.

I realize that there are many 'solutions' that everyone has out there to this problem, we've found one that works for us and has suited us well over the past four years.

A

smiley riley replied on Monday, May 12, 2008

Create an interface for the datacalls you want. Create an implentation of each of these for DB, WS etc (Strategy Pattern). You are basically creating a strategy pattern for your DAL calls. You can extend this to MSMQ qnd even add a composite pattern to use two at the same time or automatic rollovers should one become unavailable. Oh and create youself a factory for loading teh concrete types.

 

public interface DALFacade

{

public Order GetOrders();

}

public class WebServiceDALFacade

{

public Order GetOrders(){...call webservice DAL.}
}

public class DataBaseDALFacade

{

public Order GetOrders(){

..Here you can load the dataprovider by a factory class.

DataProvider provider = DataProvider.CreateProvider( some variable to determine sql, oracle etc.

provider.createparamter(.......);

provider.createClobParameter(.........);

IDataReader reader = provider.ExecuteReader(...................);

Build Order from reader (create as a seperate method and loop through fields setting values using the field name. This way you can reuse the build for every db command that builds an order object. rather than creating crazy new(...............................................................) with 100 params everytime you create the object. My view is the order of a stored procedure is much more likely to change than the field names.
}

 

}

Copyright (c) Marimer LLC