CSLA is a free 3-tier framework for .NET Framework 2.0, 3.0 and 3.5. CslaGen is a code generator for CSLA. About CSLA and CslaGen, refer to How to Use CslaGen to Generate CSLA Data Access Layer Code.
This project was born when I was trying to prove that it couldn't be done. Well... you know, it happens all the time. :)
It shows how to have a master/detail
DGV for short) using CSLA
ERLB for short) as the master list object. If you use
ERLB for the master list, auto save is a standard feature. This project also shows how to implement auto save on the detail list. As a bonus, you get both lists sorted.
This project shows a detailed example of a CslaGen project with all major issues discussed. CslaGen doesn't support
DynamicRootList generation as we speak (March 2009). Also as a bonus, you can see the changes you need to do in order to transform CslaGen object types EditableRootCollection + EditableSwitchable into proper CSLA
1.1. Technical Stuff
- CslaGen doesn't have version numbers. I use a slightly customized version (including changed template files) that you can download here.
- The solution includes CSLA 3.0.5 object code under the References folder.
- The solution builds under .NET Framework 2.0 and Visual Studio 2008.
- Microsoft SQL Server 2005 was used in this project, but you can also use the Express version.
CSLA framework has different kinds of objects and
DynamicRootList) was the last one to join the framework. It was designed with the sole purpose of data binding with Windows Forms
DGV. Under CSLA, objects follow some guidelines. I will point out only the ones that are relevant for this project:
- Root objects are the only kind of objects that are loaded and saved on their own.
- Child objects are loaded and saved by their parent (be it root or another child object).
- Usually a child object doesn't have a reference to its parent (and shouldn't need it).
ERLB is an exception to the general principle since it's a root object (root list) made of root objects.
- You can find more details on the Glossary of Common Terms.
EditableRootList is a list of objects. Those objects must be child objects. Suppose you have a list of employees as an
EditableRootList. Every employee would be an
EditableChild. Once you edit employee data (employee is a child object), in order to save it, you must save the whole employee list (the root). This isn't a practical proposition. Usually what you do is have a root read only list of all employees that allows you to choose the one you want to edit as a root object (an independent object, not a child of the root read only list). But this isn't the way
DGV works. So a new breed of objects was born:
EditableRootListBase, a root collection of root objects
ERLB is a root collection that loads objects but that allows you to save each one separately, i.e. each object in the collection is a root object. That matches the behavior of
DGV that saves each row as soon as you move to another row.
2.1. What's In A Name?
It took me some trouble to understand the "not so common terms" but this issue is not as trivial as you could think, since it reveals important things about
ERLB. CSLA templates now include a
DynamicRootList as well as a
DynamicRoot. As mentioned before, we know
DynamicRootList is another name for
ERLB. But what about
DynamicRoot? Why can't we use the
EditableRoot template? In fact
ERLB uses root objects, but not common editable root objects because they are loaded like an editable child is loaded. It turns out that CslaGen object type EditableSwitchable can be loaded both as an editable root and editable child. As we will see later, using CslaGen object types EditableRootCollection + EditableSwitchable is the closest thing to
DynamicRoot generation since it requires only small changes to get the job done.
For simplicity sake, from now on we will use only
DynamicRootList and will drop the names
ERLB. Likewise we will only use
DynamicRoot and will drop
3. Other Points of Interest
Most people turn to ProjectTracker for examples of CSLA use. Besides a comprehensive example of
DynamicRootList, this article offers a different source of use examples. You may find these examples interesting:
- use of
SortedBindingList to sort the
- use of
AddBusinessRules with the new syntax
- use of
System.Threading.Interlocked.Decrement to get unique temporary IDs for new objects
- optimistic concurrency and
DataPortal events (both standard in CslaGen)
- complete CslaGen project documentation with all less obvious options discussed (refer to the Appendix for a complete collection of screen shots)
4. Use Cases
For this example project, I chose the subject "Brands & Models". Each brand is the parent of several models and no model is child of two brands. There can be no two brands with the same name. For a given brand, there can be no two models with the same name although the same model name may exist on different brands. Note that name match is case insensitive.
As I intended to make this re-usable, at the UI (User Interface) level, the names are all around "master" and "detail". At BO (Business Objects) level, I use the real object names. In order to re-use it, you just need to replace
Model with your own object names. To make it even more re-usable, you should make it a Component.
5. The Database
The database Warehouse has a table for brands and another for models.
BrandID is the foreign key for models table.
Fig. 1 - Warehouse database diagram.
Price column is defined as
money under SQL Server. For .NET Framework the data type used is
CslaGen supports optimistic concurrency automatically if you include a SQL column of
timestamp data type. In spite of its name, this data type isn't time related at all but is really a version count starting at zero and increasing whenever there is a row update. That's why I prefer to call it
RowVersion. Optimistic concurrency checks if the present row version matches the row version at the time the object was fetched and if it doesn't, it refuses to save, warning you that the object has changed. This means some other user has changed or deleted it.
Under SQL Server run the scripts to create the database and the tables. While you are at it, also run the scripts to create the stored procedures. The project file CslaERLB1.zip includes all the scripts. You will populate the database yourself using the compiled sources.
6. The Objects
Although CslaGen doesn't support
DynamicRootList (yet), a CslaGen file (Warehouse.xml) is included in CslaERLB1.zip. I used the CslaGen object types EditableRootCollection and EditableSwitchable. Then I made some changes to the generated files and transform the set into a proper set of
DynamicRoot objects (CSLA template naming).
Fig. 2 - Warehouse object diagram (only non generated objects are visible).
BrandColl is a root collection of
Brand objects. It's a
DynamicRootList, a collection made of
DynamicRoot objects. So
Brand is also a root object.
Brand object is the parent of
ModelColl collection and
ModelColl is a collection of
- The Nested Types are the criteria for the object.
_lastID is used as a seed for temporary ID, before new objects are committed to the database and acquire the real ID (as supplied by the database).
AddBusinessRules method is responsible for adding the validation rules to the object. CslaGen has some support for validation rules. But I really prefer to do it myself. In this case, it uses the new syntax (since CSLA 2.1).
NoDuplicates method is a validation rule that checks the name doesn't exist in the collection according to the rules explained in 4. Use cases.
- In order to use
DGV, each collection must have an
Other Parts of this Article
- Document version 1: 12 March 2009
- Code version 1.1: 14 March 2009 - bug correction