Help /w DAL Design... going in circles

Help /w DAL Design... going in circles

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


Jack posted on Tuesday, November 18, 2008

I need some direction on how to best plug in my DAL.  I'm going in circles with CodeGen, a non-microsoft provider ODP.net. which eliminates a LINQ DAL, and the fact I'm probably starting with the most complicated set of BO's in my app.  I'm also pushing towards a silverlight deployment so staying as current to the latest and greatest CSLA implementation is of importance to me.

So:

I think my solution is that when I have simple one screen one - one BO type objects that I can codeGen both the CRUD sprocs and the BO.  This makes sense and is simple.

However I'm struggling with how to handle the more complicated cases (and probably making it far more complicated than it is).  I have a single BO that is responsible for getting all the data and then passing it out to the various editableLists (child/root) as well as some readOnlyLists. 

It seems to me that I either need two sets of codeGen templates or I have to start adding in flags that supress the output of simple CRUD type operations.  That being said then I want to make sure that I avoid errors with mixing codeGen properties and manual CRUD.  Easy to see adding a new field and not passing it along to the update/insert sprocs.

That sort of led me to having a separated DAL (which I have now preCSLA with a lot of my sproc calls).  But I'm confused on how best to pass the data to the DAL to do the updates.  The Fetch is easy as I can pass a DataReader back and it is always as good as the codeGen column list so updates will either not-compile or crash.

With LINQ it seems there is basically a dynamic data object that functions almost like a DTO which makes me think that is the way to go but I don't want any extra complexity if I don't need it.

Is it bad form to pass a BO to the DAL layer so my BO can change and do as it pleases and my DAL can change independently? 

ie) update myBO -> myDal.MyBoUpdate(myBO) -> use the properties I want, do my sproc, update my timestamp -> done

My current app is web forms but the new incarnation will be ASP/Silverlight and WPF where I don't need common web access. 

I've probably spent more time thinking, reading, and farting around than it would have taken to cut/paste the manual object together so I'm getting frustrated.  I am trying to force myself to resolve it via codeGen as much as possible as I frequently change/rebuild objects etc.

Any advice from the CSLA gurus would be greatly appreciated.

jack

RockfordLhotka replied on Tuesday, November 18, 2008

A couple things to think about.

First, terminology is important to avoid confusion. Business (domain) objects should be defined by responsibility and behavior, not by data. Entity objects are defined by data (technically their responsibility is to contain data). CSLA is (in my view) primarily designed to support the creation of business objects, while most ORM-like tools are designed to create entity objects.

Second, the impedance mismatch problem exists between business objects and relational data. It doesn't matter if the relational data is in database tables, or entity objects. In other words, the impedance mismatch problem exists between ORM-generated entity objects and business objects. The solution to this problem is to do mapping between business objects and entity objects - which you may or may not be able to automate.

Third, if you are using CSLA 3.6 (and I suspect you are, given your Silverlight comment) then you should look at the ObjectFactory concept now supported by the data portal. You can find information about it on my blog and in the Expert C# 2008 Business Objects book. The ObjectFactory concept allows you to more easily leverage certain types of ORM or DAL. It may or may not be helpful to you, but you should look to see if it simplifies things or not.

Jack replied on Wednesday, November 19, 2008

Rocky,

Thanks for the reply.  I've looked through the ObjectFactory and was hesitant to mix and match using the DataPortal for most things and then ObjectFactory for the others but perhaps that is the best scenario.  In terms of my specific use case I think I am still okay with the data not defining the BO.  I think I am more stuck with the fact that

Perhaps with more details you or anyone else can help push me in a more ordered direction.  I have the following:

DataEntrySessionBO          (manages a single session of working on a dataset)
   DataEntryCollectionList  (List of DataCollectionBOs)
      DataEntryCollectionBO (A set of data fields to capture [a test/interview])
        DataEntryFieldList  (list - A set of data entry fields to be captured)
           DataEntryFieldBO (A single piece of data to collect)

    FieldInfoList           (List of all FieldInfo)
       FieldInfoBO          (All the related metadata to define the data entry validation)
       FieldLookupValuesBO  (lookup values for a field)


    DataEntryCalcList       (List of all the caclulations used in the data)
       DataEntryCalcBO      (a calculation (formula) to set the value of a DataFieldBO)
          DataEntryCalcVariableList (list of related variables)
              DataEntryCalcVariableBO (A variable used in a calc - links to the underlying data field)

The reason I am struggling with how to best tie in the data piece is that I can retrieve all the data in a single stored proc at the DataEntrySession level with essentially a single cursor for each list.  If I break it up into parent children then I end up making a return trip to the database for each dataCollection (2-20x) to read in 5-100 dataFields, etc.

My other problem is that a lot of the FieldInfoBO's are re-used/shared among dataFields so I need to pull them in separately and then link them up.

My DataCalcs/DataVars are a more complicated set of object in that they provide an interface / event manager for dataFields to register changes in their underlying value which in turn re-runs the calc and then set the value for the related calculated DataField.  The calcs manage not just data values but state (required, visible, enabled, etc).  They are essential virtual objects that only exist at runtime to tie things together.

The updates (and a few inserts) can be handled by the child objects and only the DataSessionBo, DataCollectionBo's and DataFieldBO's have underlying data that gets changed.

Any input is greatly appreciated.  The more I delve into this the more I like it.

Jack

 

Copyright (c) Marimer LLC