EF and CSLA 3.8
Old forum URL: forums.lhotka.net/forums/t/7580.aspx
greengumby posted on Monday, September 07, 2009
Hi,
Currently I get an EF result set and map this to my businessbase object. However I see this mapping as redundant because essentially the EF fields are the same as the CSLA Registered Properties.
Is there a way I can have my CSLA objects inherit from my EF object through interfaces and yet keep the
CSLA functionality :)
I know its probably a long shot just want to avoid this mapping functionality.
Regards
Jeremycds replied on Monday, September 07, 2009
Hi Jeremy
I think if your CSLA business objects are an exact mirror of your database tables then you're probably taking the wrong approach to the design of your business objects.
It's been said many times on the forum but your business objects should be designed to match your use cases, not your database design. In simple scenarios they might match exactly, but usually not.
In my project I use code generation to map from my CSLA business object classes to my ORM classes so it's not really a problem for me - but you could look at the DataMapper class, which should do what you want.
I think the important thing though is that you need to keep the two concepts separated.
Cheers
CraigRockfordLhotka replied on Monday, September 07, 2009
While Craig is right, it is also theoretically possible to create a number of EF mappings for the database to match the shapes of your business objects. You can't do this all in one EF model because EF won't do multiple mappings per entity, so it is a real pain, but it can be done in theory.
I haven't had time to dig deeply into the .NET 4.0 EF implementation, but they were talking about adding some features (either in 4.0 or later) that might make mapping into managed CSLA properties possible.
If those are there, then some auto-mapping might be possible - assuming you get your entity shapes to exactly match the object shapes.
greengumby replied on Tuesday, September 08, 2009
Thanks Rocky and Craig,
The reason why I ask is I can see many use cases which would have the identical mappings.
Hopefully I can explain myself clearly :)
I have a use case that says show me an Editable List of Students with Name/Year/EmergencyContactsName/MedicalAlert
So I have
StudentSummaryList
- StudentSummary (Name/Year/EmergencyContactName/MedicalAlert properties)
In the StudentSummary(child) I would have a fetch that accepts the Entity of Student and Fills the fields via LoadProperty.
I would also need a business rule to flag the MedicalAlert based on data within Student
Now I have another use case that says show me all the student details and allow me to edit them
So I have
Student : BusinessBase (Name/Year/MedicalAlert/Address etc)
- EmergencyContact : BusinessBase (Name/Phone/Address etc)
- Family : BusinessBase (Name/Siblings)
Student would have a fetch that accepts a key and would fill the Student.
the EF statement would return all data applicable to the student including child information.
It would then pass the Entity to EmergencyContact(child) to fill itself.
Student would also have to have the same business rule as the summary to flag the MedicalAlert property.
So my issue is the lack of reuse in the Data Layer. The Fetch/Updates for each use case will essentially be repeated for each different use case.
I understand that flexibility here is paramount. (ie Should a Use Case change it would not effect other areas of the system).
However is there a happy medium :)
My thoughts were do take some basic business objects (student/emergencycontacts etc) and use these as building blocks for each use case.
So instead of UseCase to EF I would have UseCase to BuildingBlocks to Entities
For instance my Use case where I can edit all student details would become
StudentCard : BusinessBase
Student : BusinessBase
EmergencyContact : BusinessBase
Family : BusinessBase
and my StudentList would become
StudentSummaryList
Student : BusinessBase
EmergencyContact : BusinessBase
I understand that in the StudentSummaryList there are essentially wasted fields (ie fields that are not shown) but with careful use of Lazyloading this should minimize the time it takes to get the data.
I know Im rambling a bit here but essentially what I would like to achieve is for any given use case I would create a new BusinessBase or ReadOnly and then wire up existing classes to populate the screen.
Maybe Im way out of left field but hopefully someone here can put me on the right track :)
Many Thanks
JeremyxAvailx replied on Tuesday, September 08, 2009
>> So my issue is the lack of reuse in the Data Layer. The Fetch/Updates for each use case will essentially be repeated for each different use case.
You can still encapsulate your EF queries / data layer access code. Instead of writing the EF queries in your data portal, delegate to another object that manages those details for you.
This may give you some ideas...
http://martinfowler.com/eaaCatalog/repository.html
http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx
HTH.Tom_W replied on Tuesday, September 08, 2009
cds: I use code generation to map from my CSLA business object classes to my ORM classes so it's not really a problem for me
Hi Craig,
Sorry for going OT, but could I ask how are you achieving this mapping via code gen? We are using modified versions of the csla contrib codesmith templates, and are also using behavioural led object design, and I'm having a hard time figuring out how to make the two concepts work together.
Thanks
Tom
cds replied on Wednesday, September 09, 2009
Hi Tom
I built my own code generation solution - using T4 (the templating language built in to Visual Studio) and the harness available from Kathleen Dollard's company (AppVenture, I think). I built my own templates for my CSLA business object classes.
On the data side of things, I'm using LLBLGen as my ORM - and it's mostly worked out OK, though some of my data access I do by using plain ADO.NET.
For the actual CSLA data access side of things, I'm using the ObjectFactory approach, and generating these classes. So, my business object classes have a partial class file with the ObjectFactory attribute which maps to the generated class. Because LLBLGen generates classes to map to database tables, it was fairly easy to generate the ObjectFactory code to map the LLBLGen entity properties to my CSLA business object properties.
My general approach with the data access is that the Fetch method uses LLBLGen to load an entity from the database and then copies each of the properties off the entity onto the CSLA BO's properties. Updates go the other way - basically I reload the entity from the database and then update its properties from the CSLA BO, then use LLBLGen to persist the changes.
The source of my meta data is a custom SQL Server database that I maintain which describes my business objects and how they relate to the database. I have some stored procs in this database which generate an XML view of my metadata which I then consume with my code generator.
So, basically the whole thing is custom-built - nothing standard really, but it's allowed me to generate a lot of the code in my application. For the future, I'm planning to extend my code generator a bit and make it a bit more generic for use on other projects.
Does that clarify things? Where are you experiencing problems?
CraigTom_W replied on Friday, September 11, 2009
Hi Craig
That's really interesting thank you for taking the time to detail it out, much appreciated.
I've really come round to the behavioural way of designing objects - thinking about the main maintenance issues we have with our old code an awful lot of them are about one object trying to do to much - what I didn't like about the behavioural approach was the thought of having the same properties in multiple versions of a class, but since I have finally discovered the joys of code-gen this is now a non-issue.
So having got that far the next question is how to get data to/from the business objects. The code gen templates mostly work around the idea of mapping the database tables straight up to BOs, but obviously this isn't what we should be doing for behavioural code, so now my question is how to say to the code gen 'I want this field from this table, this field from that table' etc.
For the editable objects we have gone with sprocs and re-written the templates to work with these. That's OK.. ish.. but it's really only shifting the problem, because now we have to either manually write the sprocs or else code gen these (and hit the same issue of trying to say to the templates 'we want this field from here and that one from there'). For the time being we have just hand written them, but having spent two days pulling bugs out of them only reinforces my belief that this is the wrong solution.
My aim is to not have to write this plumbing code at all, but ideally to just define the mappings once for each behavioural object and let the code gen do the work - maybe a pipe dream, but it seems like the right solution from a productivity/business point of view and also to avoid the potential for bugs. It feels like there must be a solution for this... I'm just not sure what it is!
This, i am guessing, is where I should have an ORM doing the work, but that is a subject I am not well versed on - I completely get the basics and that CSLA isn't an ORM - what I need to get my head round is whether I really need an ORM and which one I should use if so - and which ones work well in both the CSLA and code-gen contexts.
So, belatedly and in answer to your question, yes it does clarify things and where I'm experiencing problems is at the most basic level!
lukky replied on Friday, September 11, 2009
Hey Tom, it's been a while...
In my "dream" world, I would use the EF designer to create the mapping between the data and the BOs, and the codegen would simply read the EDMX and generate the BOs' properties and CRUD data mapping for me.
That way, I can concentrate on the business aspect of the BO, that is define its properties thinking of the use case, and not the data (remember, EF allows you to pull the data from more than one table). Once the EF model is done, let the codegen tool generate the BO by reading the edmx directly.
That's why I'd like to see CodeSmith move in that direction rather than keeping the old school datatable based approach.
I've taken a very quick look at sculpture, and it looks promising. It seems that it aims at doing what we're both looking for. Also there's a product called Viewpoints, but I've never been able to make it work ;-) if they can iron out the kinks, it also looks promising. Both these tools take a business driven approach rather than the data approach.
See ya.
Tom_W replied on Friday, September 11, 2009
Hiya Luc
Yes, apologies, it has been a while.. when we really saw the light on the whole behavioural design approach we had to completely rewrite the spec of the current project (which is also intended to be the generic base of all our upcoming systems) we were working on, so things have been a little hectic (80 hour weeks for the last 3 months..) only really getting properly into the code now, hence the new collection of idiot questions!
As you know I'm 100% with you on EF, I'm nervous about it at this stage as it seems from Rocky's and others comments that is still fairly liable to change at this point, but it does seem like the way forward as a relatively lightweight solution. The only thing stopping me from adopting it at this point is that I can't code gen it.
I really hope Blake can get the edmx mapping into the codesmith templates, I had a thorough look at the 1.0 version of the templates and the work he'd done was superb, but ultimately it was a table driven approach, which doesn't work for us. I must update him on that in fact.
I think I remember you saying you were going to have a look at mapping from the edmx in your templates, did you ever get anywhere with it?
Thanks for the heads up on Sculpture, I'll have a look into that too.
PS: I should say a big thank you for the templates and partial methods approach lessons, that has been an absolute revelation and we use it constantly now - I owe you a drink :-)
JoeFallon1 replied on Friday, September 11, 2009
There have been complaints in the past that Codesmith templates are too data-centric and that they only let you pull data from one table at a time. I still do this most of the time for the Code Gen level of my BOs and then I hand code the extra fields from other tables. I like having Bos that cleanly map to my tables. I usually encapsulate them inside a higher level BO to handle the use case. I call those Use Case Controller objects (or Unit Of Work - UOW). They do the high level coordination of BOs for the use case. i.e. fetch the Root BO and its children, some Read Only Collections, a few NVLs, etc. Then the screen binds to the Root BO and the extra data is used for dropdowns, etc.
But Codesmith is far more flexible than that. I just don't use a lot of the advanced features. I think some people have defined XML files that Codsmith can read and use to generate BOs.
In some other cases I have designed SQL Server Views (of a many table join) and then pointed Codesmith at the View instead of the table and it spit out a whole BO.
So a lot of this can be overcome with more training and experience with Codesmith.
Joe
Tom_W replied on Friday, September 11, 2009
Hi Joe,
thanks for that, can I ask a couple of questions;
JoeFallon1: There have been complaints in the past that Codesmith templates are too data-centric and that they only let you pull data from one table at a time. I still do this most of the time for the Code Gen level of my BOs and then I hand code the extra fields from other tables. I like having Bos that cleanly map to my tables. I usually encapsulate them inside a higher level BO to handle the use case. I call those Use Case Controller objects (or Unit Of Work - UOW). They do the high level coordination of BOs for the use case. i.e. fetch the Root BO and its children, some Read Only Collections, a few NVLs, etc. Then the screen binds to the Root BO and the extra data is used for dropdowns, etc.
How does that work with regards to db transactions when it comes to writing the data back? Is it still possible to get all the writes inside one transaction?
JoeFallon1:
In some other cases I have designed SQL Server Views (of a many table join) and then pointed Codesmith at the View instead of the table and it spit out a whole BO.
That's exactly what we've done for the readonly objects in a lot of cases. The only issue we have there is we are using Rocky's approach for refreshing locally held readonly objects when the editable versions change, which works well except where the readonly object has data that the editable version doesn't (e.g. an editable sales order line has the stockId, but the readonly version has the stockItemName say) - in that scenario we need to roundtrip the database to get the stock item name.
For the readwrite objects we keep tripping over the 'views can only write to one table' restriction, so have ended up with sprocs. It's this mix of sprocs and views that nags me, seems messy and like there must be a better way.
JoeFallon1:
So a lot of this can be overcome with more training and experience with Codesmith.
That definitely applies to us! It is a great tool and now I have got my head round it's breakpoints and debugging codesmith templates in VS it is all making a bit more sense. Incidentally; we took you're advice and made our templates work for us, rather than just code-genning the first time and never again - it has already saved us days of work when we have needed to re-gen, so thank you for stopping me taking the easy way out!
I take my hat off to those who produced the original cslacontrib templates too... more people on the list of of people I owe a drink.
asp2go replied on Tuesday, October 20, 2009
Excellent and interesting discussion. It seems that we still need some enhancements to the tools out there!
@Tom - Note also that if you are working with a mod version of the CSLA Contrib templates there is a CslaXml file in there that allows you to build your objects by defining the tables/fields/attributes to be included in an Xml file and the object doesn't need to be from a single table. Then the Linq 2 Sql that is generated addresses the various tables. If you weren't using L2S you could likely leverage the template to build the dal 'your way'.
I'm currently doing exactly what you are working on and looking at potentially building a visual designer that would create that Xml and allow you to more easily create the BO's. The combination of ideas from various tools and templates out there will get us there eventually I think. The Sculpture solution looks very impressive and is the most advanced version I've seen of what we are after here - it's worth looking at but I'm still getting several issues with the beta release bugs.
There really are a lot of options - I've looked at Codebreeze, Codesmith's new templates, CodeComplete, CslaGen, CslaContrib and a couple other options lately all of which have great features. In any event I'm going to focus on a custom Xml definition driven approach that is capable of creating behavioral rather than data-centric BOs.
Cheers
Tom_W replied on Monday, October 26, 2009
asp2go: @Tom - Note also that if you are working with a mod version of the CSLA Contrib templates there is a CslaXml file in there that allows you to build your objects by defining the tables/fields/attributes to be included in an Xml file and the object doesn't need to be from a single table. Then the Linq 2 Sql that is generated addresses the various tables.
That's really good info, I knew you could define the tables via xml, but didn't realise that you could span multiple tables. You don't by any chance have an example of a multi table editable object xml definition do you? Or know where there is any detailed documentation for this with regards to the contrib templates?
If you weren't using L2S you could likely leverage the template to build the dal 'your way'.
You're absolutely right, I think I'm probably suffering from there being too many options and not being able to decide on one particular one. EF, lots of the ORM frameworks, sprocs etc could all fit in here in the code gen.
Perhaps the problem is really that I'm fixated on using a visual designer to speed the mapping of the database structure to the objects. If I let that go and switch to using xml definitions for the mapping, or take Craig's wise sounding route of building the mappings into the database, then the solution becomes easier... hopefully!
I think my other problem is the belief that 9 times out of 10 in programming someone else will have solved the issue first, it feels like I'm reinventing the wheel and so must be missing something obvious.
I'm currently doing exactly what you are working on and looking at potentially building a visual designer that would create that Xml and allow you to more easily create the BO's. The combination of ideas from various tools and templates out there will get us there eventually I think. The Sculpture solution looks very impressive and is the most advanced version I've seen of what we are after here - it's worth looking at but I'm still getting several issues with the beta release bugs.
There really are a lot of options - I've looked at Codebreeze, Codesmith's new templates, CodeComplete, CslaGen, CslaContrib and a couple other options lately all of which have great features. In any event I'm going to focus on a custom Xml definition driven approach that is capable of creating behavioral rather than data-centric BOs.
Is that a project you are doing for yourself, or a commercial offering? If it's for sale, I suspect there'd be a market!
I see Phil is now using EF in CodeComplete, I'm not sure if it can generate from the 'top' of the EF model, but if so that could be worth looking into.
RockfordLhotka replied on Monday, October 26, 2009
I really have two points – one is a repeat.
Good object models almost never match the database shape. Sure,
some objects do. But many important objects won’t match the database
shape. Few (if any) ORM tools actually provide the flexibility to map a table
(in whole or part) to n different object types. Or to map n different tables
(in whole or part) to a single object type. EF doesn’t do this – in
fact it can only map a table once as I understand it.
So while it is a great goal for an ORM to do this, after 15+
years of people building ORMs and failing to achieve the goal, I’m not
holding my breath…
The second point deals with ObjectFactory and EF. I put ObjectFactory
into CSLA .NET in anticipation of EF someday being powerful and flexible enough
to instantiate CSLA .NET object graphs. That would make it possible to create an
EfObjectFactory that did all the work based on an EF mapping file. For this to
work a couple things must be true:
·
EF must allow CSLA to instantiate every object (root,
collections, child objects, etc) so CSLA can initialize the metastate (IsDirty,
IsNew, etc).
·
EF must allow CSLA to get/set property values – especially
since fewer and fewer objects use private backing fields, and many objects have
read-only properties, etc. In other words, EF must allow CSLA to call
ReadProperty() and LoadProperty() to get/set the values
It may be the case that EF 4.0 has these capabilities – I haven’t
had time to look. Certainly they have improved POCO support, but the question
is whether they provide extensibility points for the create an object instance,
set a property and get a property operations.
Ultimately I hope these extensibility points do exist, because
it should then be possible to create an EfObjectFactory that you simply invoke
for an EF query, and you get back a fully populated CSLA object graph as a
result.
I should point out though, that there’s virtually zero chance
that the EF designer would create your business classes. They might map to
classes you write, but their designer is very unlikely to generate CSLA code :)
The most you might hope for is that they use T4 templates for all their
code-gen, so someone could entirely rewrite all the EF templates to code-gen
CSLA output. I don’t think that’s true in EF 4.0 – but maybe
it is?
jbudimir replied on Wednesday, November 11, 2009
Hi.
Just want to inform you about my work in progress. Currently, I'm developing T4 templates that will generate CSLA classes, using EF designer. At this time it is possible to generate some basic classes (EditableRoot, EditableChild, EditableChildList, ReadOnlyChild, ReadOnlyRootList..). There is a VS2010 project and some sample videos on my CodePlex site: http://t4csla.codeplex.com/
This is work in progress so I'll continue updating this site, and informing you here about the changes.
Edit: this is a pre-alpha version, used just to test concepts.
Regards,
Josip
lukky replied on Sunday, January 03, 2010
Hello Josip,
I have just tried your t4 templates, and I think this is a great idea. I've been looking for something like this for some time.
Do you intend to develop this any further ?
Do you need any help ?
Regards
Copyright (c) Marimer LLC