Examples of Data Access Layer working with CSLA framework?

Examples of Data Access Layer working with CSLA framework?

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


RichardETVS posted on Wednesday, February 28, 2007

In the CSLA; the business objects have the responsibility to access the database. I would like to have a separate access layer, so I could change of database without modifying the BO. I could implement a simple data layer, an object with method who’ll get object to save, update, etc. as parameters, like MyDataAccesObjectLayer.Save(aCustomer).

 

But how that could work? In order to save aCustomer, MyDataAccesObjectLayer should know the private property of aCustomer? OR THE DataLayer object could in a propriety of the object to save; so it would have access to its members?

 

Do you know any example or framework that does that?

 

Cordially

 

Richard

Jimbo replied on Wednesday, February 28, 2007

Yes you can do this, but it discards the use of  "Mobile Objects" and the goodies of the proxies that csla data portal provides.
We do this in a number of applications that need to support legacy COM+ etc server architectures ( although gradually migrating to remoting and System Transactions instead) .

You can bypass csla DataPortal simply by overridiing Save() in BusinessBase etc and pointing your updates to your own dataportal service (tcp preferred).
Rocky does not go into the details of a tcp remoting service - but I can tell you that it really rocks compared with using Soap and IIS etc.

jimbo







Jimbo replied on Wednesday, February 28, 2007

I should add that in these scenarios we are using simple old fashioned DTO's and parameterized calls that do not have any reference to the BO's on the server.



RichardETVS replied on Wednesday, February 28, 2007

Thanks for the answer. My idea was not to bypass the data portal. The BO would have their dataPortal methods, but instead of implementing them, they would use an access data layer.

 

By example, in a BO, DataPotal_Fetch(), instead of doing some SQL, would call the data access layer. Like this, we would keep the benefits of the CSLA framework.

Jimbo replied on Wednesday, February 28, 2007

csla does not dictate the data access or provider that is to be used ( although it is ms sql centric by default) . You can use whatever data access provider (MySql, Oracle, XML, CSV, Excell, Access etc ) you wish to code for in each of  your DataPortal_Fetch, Insert, Update etc methods. Clearly you would also have to replace  datareaders etc as appropriate for loading datarows or otherwise provide suitable adaptors for the type of rowsets that you get..
If you wanted to be able to use alternate or switchable sources than perhaps it would require switchable cases in each method dependent on the provider. This suggestion of course is not ideal as it would blow out the code base in the objects and any future provider changes would similarly require rebuilding.
How to have a universal persistence layer without provider customisation is beyond me at this point

RockfordLhotka replied on Wednesday, February 28, 2007

Here are a couple relevant articles:

http://www.lhotka.net/Article.aspx?area=4&id=b99dfec2-c079-4b85-98df-ea3582c28386

 

http://www.lhotka.net/Article.aspx?area=4&id=2e6468d6-9a02-4f0e-a31c-a7eecc268e1b

andrewem replied on Wednesday, May 07, 2008

Hi,

I have to say that after reading these posts I am completely confused.

The goal, the way I see it, is how to separate those Data Access methods (whose code might be using SqlConnection or OracleConnection) are different based on which DBMS's you are using but at the same time to keep all your business properties separate so you don't have to repeat them. The fact that a projects start date has to be less than the projects end date doesn't change regardless of what database you are using. And, there is a valid reason for supporting other platforms such as Oracle. Most of our clients are large (city sized) and we can't just say use SQL Server. We also can't go releasing a whole new application each time we decide to support a new system.

We have a model that works very well through inheritance at least with 1.1. It uses a factory layer to create the objects as plugins by loading the assembly and using the System.Activator classes (I think this was discussed in the first book) and then using protected variables instead of private variables to be able to set the values of the properties (instead of setting them directly). I'm not sure where my predecessor got it from, but I would like to make it more in-line with the books now that we are trying to upgrade to 3. However, the books don't describe this. And, as I said after reading those two articles I am completely confused because I'm looking for a clear and simple method that works with the latest framework (no VB6/COM discussion).

I believe there is a need for this. Do we have a clearer solution?

A

tmg4340 replied on Wednesday, May 07, 2008

What the heck... I'll take a stab at this.  Slightly longer post coming...

The concept of the "Separated Interface" pattern is that you create a series of interfaces that other assemblies use to talk to each other.  The interfaces are put into their own assembly - thus, the interfaces must be public in scope, so that they can be used b other projects.

(Yes, you could mark them as internal, and use the InternalsVisibleTo attribute, but... well, IMHO, that doesn't make any sense.  If you want to use the interfaces in other projects, make them public.)

In your BO classes, you would implement the appropriate interface.  Whether you implement it implicitly or explicitly depends largely on what you want to use the interface for.  If the interface methods are useful for the UI developer, then implement the interface implicitly.  If they are not, then implement the interface explicitly.

So, for example, if you had an interface "IWidget" with two methods - "Foo()" and "Bar()" - and you chose to implicitly implement the interface, your class would look something like this:

public class MyBO : BusinessBase<MyBO>, IWidget
{
    public void Foo()
    {
    }
    public void Bar()
    {
    }
}

And your UI programmer could access those methods from their instance of the "MyBO" class.

If you choose to implement them explicitly, your class would look something like this:

public class MyBO : BusinessBase<MyBO>, IWidget
{
    void IWidget.Foo()
    {
    }
    void IWidget.Bar()
    {
    }
}

And those methods would not be available to the UI developer unless he cast his "MyBO" instance to the interface.  Given that the interfaces are being used for the business layer to talk to the data layer, you likely wouldn't reference the interface assembly in the UI, and thus your UI developer couldn't cast the BO to the interface.

If the UI developer needs some of the interface, but not all of it, then you have to implement the method twice - once with the "void IWidget" style, and once with the "public void" style.  This does not confuse the compiler, because the explicit implementation has a different scope within the class, so there's no signature clash.  The implicit implementation in this scenario actually has nothing to do with the interface at that point.

In either case, the interfaces allow you to expose whatever you like from your business object to the data layer, regardless of its scope within the BO.  Data that is non-public in the BO (like IsDirty, IsNew, etc.) can be exposed via the interface without breaking BO encapsulation.

In your data layer project, your data-access methods don't take BO's as parameters - they take your interfaces.  Thus, the circular-reference problem is solved, and you can pass your BO into your data-access layer without a problem.  After all, at that point, all the data layer knows about is what the interface tells it.

Am I recommending using this pattern?  Not necessarily.  Because, ultimately, we want CSLA to talk to multiple database platforms, right?  Well, we don't have to use Separated Interfaces to do that.  You certainly can, and it's a perfectly valid technique.  But there is another option.

And, before I start on this topic, I want to stress that CSLA is not SQL-Server-specific by default.  Yes, Rocky's examples use SQL Server.  But what do you expect from a Microsoft Regional Director who works for an MS-technology-only company?  Stick out tongue [:P]

CSLA imposes no platform affinity for your data.  It imposes a method structure that you have to follow to get data into and out of your BO's, but where that data resides is up to you.  If you want to allow for multiple database platforms, then your DP_ methods can't contain any platform-specific code.

One possibility is to rely on .NET's base classes for the DB stuff - DbConnection, DbParameter, DbCommand, etc.  You code using those in your DP_ methods, and you get those objects via factory methods in your data layer.  The factory methods determine the proper subtype to provide based on whatever you like - configuration entries, compiler switches, or the number of hairs on your cat.  I generally recommend the first option, but whatever gets you there.  Smile [:)]  This is essentially what MS's DAAB in the EL does, or allows you to do.  I happen to have built my own version, but it's the same basic concept.

Another option is to go the DTO route.  This is conceptually the same as the Separated Interface idea, and you'd probably put your DTO's into a separate assembly, just like your interfaces.  But instead of interfaces, you have classes that function as nothing more than data containers.  In DP_Fetch, you would call a method in your data layer that returns a DTO, and you would populate your BO from that DTO.  In DP_Insert and DP_Update, your BO creates a DTO, populates it, and passes it into your data layer.  DP_Delete could do the same, but IMHO that's overkill.  This introduces an extra data-copy step - from the DTO class to your BO and vice-versa - but the DataMapper class can provide some help in the right circumstances.

And before you ask, it's not generally a good idea to use the DTO as your data container in your BO and just delegate to it.  You certainly can do it, but you run into some pretty hairy problems with parent/child relationships, and a lot of the code simplification that CSLA 3.5 provides gets kinda hinky when you're trying to marry it with a DTO.  If you're not on 3.5 yet, then that's not a problem, but it still makes for some funky code.  It also introduces a fairly tight coupling between your DTO and your BO, which limits your flexibility later on.

If forced to make a choice between interfaces and DTO's, I'd probably choose DTO's.  Interfaces are pretty inflexible to change, whereas a DTO can be subclassed if necessary.  DTO's also work fairly well in SOA and other n-tier scenarios, as the DTO's can be passed in and out of web services fairly easily.  Of course, you can use interfaces too - but if you use interfaces, then you have to consider that your BO is getting serialized and passed into the web service, which could prove problematic depending on what you're trying to do.  Your method might be asking for an interface, but it's still objects going in and out...

When you start talking about DTO's or interfaces, pretty soon people start talking about object state.  Depending on how you implement things, CSLA-specific properties like IsDirty, IsNew, IsDeleted, etc. have to be in your interface/DTO, so that your service code knows what to do with the DTO it's received.  You can certainly do that, but you can also just create different methods for the different operations.  DP_Insert knows the object is new - otherwise, that method wouldn't have been called.  So your DP_Insert code calls a "InsertObject" web-service method, while your DP_Update code calls an "UpdateObject" web-service method.  It's not as "chunky" as some people might like, and I can certainly see where that doesn't scale well in a parent/child situation where you want to send an entire object graph in one go and have the web service figure it out.  So, in those situations, you really do have to include object state in what you send.  Besides, if you're talking about an implementation where the business layer and the data layer have a web service between them, you now have another trust boundary, so including state at that point is pretty much a must.  But since those properties are present no matter what, you can create a base interface/DTO for that stuff, and have everything else inherit from that.

HTH

- Scott

RockfordLhotka replied on Wednesday, May 07, 2008

You can look at the CSLA .NET 3.5 ProjectTracker code - it uses an external DAL created using LINQ to SQL. The model itself doesn't allow for swapping out different DAL implementations, but it is a relatively small step to get there. I am hopeful that ADO.NET EF will allow a similar implementation where you don't need to worry about swapping out the DAL at the DataPortal_XYZ level, because EF will better encapsulate the solution - time will tell.

In terms of getting the business object's fields loaded with data, there are many options. ProjectTracker 3.5 uses a model not unlike previous versions, and quite similar to the DeepData example on my web site.

But you can use partial classes (especially if you create separate projects for your client and server assemblies - using Visual Studio's linked file capability to share the actual core code files). Or you can use an inheritance model as you describe.

malloc1024 replied on Wednesday, February 28, 2007

Another alternative you might want to consider involves the Separated Interface pattern(Fowler).  You could create an explicit interface for each BO and place them in a separate assembly.  Each BO would implement its own explicit interface and pass that to the DAL.  The key is to use explicit interfaces and not implicit interfaces.  Explicit interfaces allow you to access private properties when you cast to the interface.  This allows you to load and save objects from the DAL.  Any code that does not have a reference to the explicit interfaces assembly will not have access to the private properties.  This allows you to hide private properties from the presentation layer while exposing them to the DAL.

RichardETVS replied on Thursday, March 01, 2007

Thanks for the links, Rocky.

First time I heard of  Separated Interface pattern ;) . And I do not know the difference between explicit and implicit interfaces. I’ll invoke my all knowing god, Google!

Edit: well, I found things on explicit interfaces, like:

The class member IControl.Paint is only available through the IControl interface, and ISurface.Paint is only available through ISurface. Both method implementations are separate, and neither is available directly on the class. For example:

SampleClass obj = new SampleClass();
//obj.Paint();  // Compiler error.

IControl c = (IControl)obj;
c.Paint();  // Calls IControl.Paint on SampleClass.

ISurface s = (ISurface)obj;
s.Paint(); // Calls ISurface.Paint on SampleClass.

So the idea is to implement a public interface to expose private properties, and as this public interface is not available in the UI, the private properties stay hidden for the UI developer? That seems really interesting.

ajj3085 replied on Friday, March 02, 2007

RichardETVS:
So the idea is to implement a public interface to expose private properties, and as this public interface is not available in the UI, the private properties stay hidden for the UI developer? That seems really interesting.


Not quite; you want an internal interface, not a public interface.  If you make the interface public, then the explicit implementation of the interface will be visable as well.  If the interface is internal and you implement it explicity, then only classes internal to the assembly can see the private bits, but your UI code will still not be able to see it.

RichardETVS replied on Tuesday, March 06, 2007

ajj3085:
Not quite; you want an internal interface, not a public interface.

Well, I do not get it, then. When I read “You could create an explicit interface for each BO and place them in a separate assembly”, it seems to me that I can’t use internal scope.

ajj3085 replied on Tuesday, March 06, 2007

That's correct, I'm not sure where malloc was going with his idea of seperate assemblies.. but if you put the interfaces in a seperate assembly, that assembly needs to be seen by any other assembly that uses your BO.  That ends up defeating what you want to do, which is keeping the implementation of the interface on your BO private.

RichardETVS replied on Tuesday, March 06, 2007

But f the interface assembly is referenced only the BO assembly and the DAL assembly, and the implementation of the interface are explicit, it seems to me that the encapsulation is preserved, because only the DAL will have access to the private fields of the BO.

ajj3085 replied on Tuesday, March 06, 2007

I'm sure that anything which references your BO assembly will also have to reference the interface assembly, and thus could use that interface to modify the property values bypassing the normal Csla properties (i.e., the rules wouldn't run, etc.). 

The only way to truely prevent this is to keep the interfaces internal to the BO assembly.  You would then need some kind of mapper which takes the DAL object and sets properties via the interface.

Attached is a sample application which illustrates the problem.

malloc1024 replied on Tuesday, March 06, 2007

You could keep the interface internal to the BO assembly and use the
InternalsVisibleTo attribute to expose it to the data layer.

ajj3085 replied on Tuesday, March 06, 2007

Wouldn't that require a circular reference between the BO and DAL layers?

malloc1024 replied on Tuesday, March 06, 2007

Your’re correct about the circular reference.  I should have thought before I responded.

malloc1024 replied on Tuesday, March 06, 2007

You could try to set the separated interfaces to internal, place them in their own assembly and use the InternalsVisibleTo attribute to expose it to the Business and Data Layer?  Would that work?

malloc1024 replied on Tuesday, March 06, 2007

It works in VB.NET but it appears that is doesn’t work quite as well in C#.  I just tested it in C# and it appears the presentation layer needs to have a reference to the separated interfaces assembly.  This is not the case for VB.NET.  The presentation layer doesn’t need to have a reference to the separated interfaces assembly in VB.NET.  I am not sure why it works in VB.NET and not in C#.  Anyway, even if the presentation layer had a reference to the separated interfaces, it would not be able to access the hidden properties of an object unless it was casted to its separated interface.  However, this does not work as well.

ajj3085 replied on Tuesday, March 06, 2007

Hmm, interesting that vb.net doesn't require the reference.

In C#, if the presentation layer references the interface assembly (which it seems to require), you still have to cast the object to the interface to access the properties to use the explicit implementation as well.  I'm not sure i'd want to trust though that a UI programmer wouldn't do so because they feel the object isn't accepting a value it should..

Copyright (c) Marimer LLC