Designing N-Tier Applications with OpenAccess ORM

by Todd Anglin | Comments 11

A very important question recently crossed my inbox, and it essentially asked:

“Can you design and build Enterprise-grade n-tier applications with OpenAccess? Or does it force you violate principles of good multi-tier application design to make the ORM features work?”

It was a great question and I was surprised to find that there is not more info in the online docs to address this. So, to help everyone benefit from this question’s answer, here are some details about building n-tier applications with OpenAccess.

WHAT DOES GOOD N-TIER ARCHITECTURE LOOK LIKE WITH OPENACCESS?

Let me preface this discussion by saying there is no “absolute” right or wrong way to architect an application. The approach highlighted here is just one way that will help you build applications that use OpenAccess with clean separation of concerns and respect for principles of multi-tiered application design. With that out of the way, a “typical” multi-tier app built with OpenAccess should look something like this:

  • Entities (or Model): Contains your persistent classes; Project is “OpenAccess Enabled” to define Persistent Classes (PCs) and includes DB mapping info in the config file. The persistent classes in this project can be created via the Forward or Reverse Mapping OpenAccess wizards.
  • Data Layer (Optional): Optional, in my opinion, since the actual “data plumbing” will be handled “automatically” inside OA. I prefer to skip this layer, but it can be used for storing your LINQ queries and returning data to your business layer, if desired (and if you don’t want LINQ in your business layer).
  • Business Layer: Provides “Repository” (or “Manager”) classes that define operations on model (such as FindAll, FindById, Insert, etc.). Acquires ObjectScope used to manipulate objects in the database. “OA Enabled” to consume PCs, which adds ObjectScopeProvider to project (but does not add mapping info to project)
  • Service Layer (Optional): To build an app that is ready for client-oriented technology (like Silverlight and ASP.NET AJAX 4.0), it is usually smart to build a service layer on top of your business logic. The service layer consumes your business layer “data manager” classes and exposes the operations as service endpoints.
  • Presentation Layer: Consumes business layer repositories (if no service layer) or consumes services. The presentation layer can be completely ignorant of OpenAccess and it has no need to be “OA Enabled.”

The project linking would look some like this:

Presentation consumes Services consumes Business consumes Data (if present) consumes Model

The only time you might “break” this direct inheritance tree is if you want to re-use your model classes in your other tiers for easier data binding (i.e. I want to bind to return a List<ModelType> vs. some intermediate class type). Still, in that case, you’re only using the class model for binding- you’re not doing any data access outside of your data access tier. Here is the same architecture in picture:

OpenAccess Architecture Layers

WHAT PROJECTS NEED TO BE OPENACCESS ENABLED?

One of the bigger points of confusion when it comes to using OpenAccess in n-tier applications seems to be which layers require you to run the “OpenAccess Enable” wizards. To be clear, there are two types of OpenAccess enabling provided by the wizard in Visual Studio:

1. Project Defines Persistent Classes: Adds configuration info to App.Config containing DB mappings, Adds refs to OA assemblies

2. Project Consumes Persistent Classes/Connects to DB: Adds references to OA assemblies, Adds ObjectScopeProvider class (for help managing ObjectScope), Adds connection info to project configuration file

In general, the only layers that need OA enabling are your model (where your persistent classes are defined) and your Data or Business layer (or whichever layer you’re using to actually execute queries against the DB).Other layers, like your Presentation layer, do not need to be enabled. And in all cases, when you run the wizard, you’re not adding references to other projects in your solution- just to the OpenAccess assemblies.

I hope that helps clear-up the general approach to using OpenAccess to build n-tier applications. OpenAccess is definitely powerful enough and flexible enough to handle Enterprise architectures, so it’s usually just a matter of understanding how and not if OpenAccess can do what you want.

About the author

Todd Anglin

Todd Anglin

is an avid HTML5, CSS3, and JavaScript advocate, and geek about all things web development. He is an active speaker and author, helping developers around the world learn and adopt HTML5. Todd works for Telerik as VP of HTML5 Web & Mobile Tools, where his current technical focus is on Kendo UI. Todd is @toddanglin on Twitter

11 Comments

Jonathan
So what Cloud storage providers are thinking about supporting? Obviously Azure / MS SQL Data services
Richard Brown
Hi Tom,

Thanks! I've been looking for some clarity like that for a few weeks now, downloading all the sample code and browsing forums and found nothing directly on the Telerik site.

On Telerik.com's code library I was able to download a best practices sample. While this was intended more to show how best to handle scope, it also had a basic framework for a tiered model with a project called Persistent Objects with  BLL, DAL, and BO directories. However this project seems incomplete and a little illogical, with the website project still referring directly to the OpenAccess class and the ObjectScope and this confused me somewhat. Does anyone at Telerik have a sample project with a the tiered approach fleshed out a little to help people like myself get a fuller understanding.

This has been very helpful!

Regards,

Richard.
Pratik
Todd,

Thanks for the excellent post.  Really clarifies a lot of details.
We have been using Telerik's ASP.NET and Winforms controls for the last 3 years and we love them.  With the newer product lines though, these details will be really helpful.

I would like to see a finalized enterprise-grade n-tier application sample from Telerik as well.  I think that will definitely get a buy-in from people like me and Richard to use OpenAccess in the applications we design and develop.  I think it will be great if someone at Telerik can do this soon.

Pratik
Henrik
Hi Todd (and others)

We have been working with OpenAccess for the last 3+ years and have built an architecture like the one suggested here. We have the exact same layers and use WCF to expose service endpoints. Clients includes: Other services (WCF, asmx), ASP.NET webs, SmartClients, Mobile Clients, etc.

However, exposing WCF services with data contracts including persistent capable classes (entities) has some drawbacks in my opinion. I will share those with all you now, take notice of them if they apply or ignore them if the don't :-)
We found another solution (more on that later), but first the drawback as I see them:

- Highly navigatable entities

We designed the entities to be highly navigatable meaning you can easily navigate the entities. Say you have an order, you can navigate the orderlines or the customer who placed the order...and if you have an orderline you can navigate back to the order. Basically, we are using the core principle of "persistence by reachability".
However..if you do this one can expect that when the DataContract (of your WCF method) gets serialized on the wire, lazy loading will be in effect for those association you did not already load, because the serializer traverses your DataContract object....and for lazy loading to be in effect, the objectscope that was used to retrieve the object down in the data/persistence layer must still be alive.
Size of the serialized xml and circular references (back references of the highly navigatable entity) is another issue.

- Exposing the full entity as a DataContract

We considered it "bad pratice" to expose the entity as a DataContract, because the might be some details of the entity, that does not need (or even worse: are not allowed) to go to the client (asp.net, smart client, whatever)
As per the serializer issue above everything that can be navigated in the entity WILL be serialized by the DataContract serializer when it goes on the wire.

- Transactions

Associated with the issue of the object scope stated earlier. Where should my transaction begin and end?? When lazy loading can happen as late as the serializer?

There were several other minor issues, which I can't think of yet, but as always we found a solution to accomodate our needs:

We defined the transaction demarcation to be the business layer. That's where the transaction (the OA one) starts and ends (begin, commit or rollback). To do this we need the objectscope to be at hand.. and we needed a place to "store" the retrieved object scope for the remains of the transaction since other (lower) layers might need it. The solution was to encapsulate the scope to a "context" object and "bind" this context object to the executing thread. This way we could retrieve the context object (and the scope) where we needed it.

The transaction demarcation was at the business layer. This means that before the request moves back to the service layer everything involving OA must be finalized (the scope is disposed). This involved creating a simplyfied "forward-only" navigational DataContract model to be exposed in the service layer and returned from the business layer. In other words a mapping exists between the entity and the datacontract object exposed in the service method. Say you have and Entity.Order and a DataContract.Order, likewise with the OrderLine class...  but the DataContract:OrderLine does not have a reference back to DataContract.Order. This is what I mean with "forwar-only" DataContract object.

Doing this mapping on the way in (to the business layer) and on the way out (of the business layer) solved all the above issues:

- The payload of the xml on the wire is smaller (forward only navigation and a simplifed model
- No lazy loading occurs in the serializer, since it only operares on DataContracts objects.
- Transaction demarcation is defined, the service only only acts as transport/exposure. Thus one can skip the service layer or have it.. Transactions will still work, because it sits in the business layer.
- The mapping between Entity classes and DataContract classes can include logic to "semi-automate" the process or take decisions based on the context. Details of the entity that are not allowed to go to the client were left out of the datacontract class.


It has one drawback though:
A mapping layer, but I think it is worth the bucks... and it performs very well.

Thanks for listening - gosh the post became a long post...



Jan van Veldhuizen
OpenAccess ORM looks great, but I have one concern however.

My application should be configurable to support either an SqlServer or an Oracle database, according to which database is available at the customer's system.
Of course I should be able to use the same model for both databases. The programmer of the Logic Layer should not need to know which database is at the other end of the Data Layer.

Is this possible with OpenAccess ORM?

Richard Brown
Henrik,

That solution sounds great. Is there any sample code, or anyway I can see in more detail how you handle the scope and the mapping?

Thanks!

Richard.
Lucifer
Hi Todd

Do you have an Example of this?

Thanks
Alexander Becker
Hello,

excellent post!
I am looking for an example implementation containing all mentioned layers, too.
Especially the DataLayer and the LogicLayer are interesting to me.
Is there anything available by now? If not, can I expect it soon?

thank you
alex.
Hugo Augusto
This is just wrong. The only layer where you don't force OpenAccess dependency is in the Presentation Layer. This doesn't allow for absolutely zero coupling with the domain model generated by OA. Automatically mapping the database to our own BOs would increase the abstraction level between layers. Building Assembler classes where we have to manually convert OpenAcess BOs (Generated Model) to our own BO's for the sake of abstraction, will make a project to complex to maintain and frankly, would break the purpose of using OpenAccess at all. Till now, I haven't seen an example where this issue is addressed. Any ideas on this?
Ryan van der Kooy
Todd, at the swfcc in Ft. Meyers, FL you started to describe a reposity pattern for a Data Access Layer.  It would be great if you could go into further detail on how that fits in with this pattern.  Thanks in advance. -Ryan
Ryan van der Kooy
*repository

Comments

  1.    
      
      
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)
Read more articles by Todd Anglin - or - read latest articles in Developer Tools