Archive for the ‘technical’ Category
TypeMock gets it wrong on ORM
The fellas at TypeMock recently discussed “Mocking only what you own” in response to a cogent though not very helpful post from normally lucid author Mark Needham.
Mark basically said don’t mock external dependencies SUCH AS Hibernate. Not any external dependency. Without getting into the functional versus unit/mock testing discussion I agree with Mark. Why write tests for an ORM. It should work. That’s why we use ORM’s.
The TypeMock guys butchered the whole thought though suggesting that Mark should have a DAL that Hibernate uses. Isn’t the beauty of ORM’s that is generates the DAL for you? I really don’t know where they are coming from with these thoughts – but it’s not helpful from a company that makes mocking/type isolator frameworks.
My advice to TypeMock: take a stand. Say it should be done one way or another, or, if you don’t understand ORM’s like hibernate don’t speak on it.
Refactoring Quickly with TDD
The situation. I have a class, Edc, that has an interface:
IEdcFinder
It needs to be composed with one of a few data lookup methods. Like a method connecting to SQL or a method connecting to XML. I don’t want the caller to have to configure this finder object with the data method. I’d like to make it easier. Especially since this finder object is already being injected into another class as a pluggable object.
So, logically, move the construction of the finder to a factory method and compose the data method with it then. I created a Factory class:
class EdcFinderFactory
But then, we have another class doing work. So, with TDD, I switched the interface to an abstract class thinking I could use inheritance to mark all subclasses with a private constructor as well – and made the tests pass. Good.
I was feeling OK about how things were going, but not thrilled. I had working code but something smelled. I realized something: there is only one class implementing IEdcFinder and that is EdcFinder. Let’s remove duplication.
Remove: EdcFinderFactory
Remove: IEdc
(There were actually many small steps in here making sure the system still passed.)
Left with:
EdcFinder
public EdcFinder(){..}
public Create(){…inside here we create an EdcFinder composed with IReadSomeData}
So, EdcFinder became a simple concrete class with it’s public constructor and the factory method. And, as always, I ran the tests: Pass. Then the constructor was marked private. Pass. Remove the old abstract class (which was an interface to start with).
Now there was less code, less interfaces and easier to read code. I was able to implement the “Replace Constructor with Factory Method” refactoring in just minutes and I know everything still works.
With TDD and my test suites I could change with out fear.
And two days later, I looked again and removed this entire class realizing it was unnecessary and the data method could be simplified with Func<T>. I switched everything in about an hour. Red, Green, Refactor.
Bon.
In DDJ
There is something about paper. In lieu of that, we have blogs. Summary: I was recently published in Dr. Dobbs and now the online version has appeared. It was a fun experience writing the article – it helps when you’re passionate about the topic of course. Have a read.
Ajax and the Service Gateway Pattern
Introduction
It is easy to forecast how many widgets you can ship when you are creating them in the factory behind your office. It is another story when those widgets are being created in another factory that you do not own. You are now a customer of your distributor, but as a market economy would dictate, your customer’s do not care where the product comes from. They just want to know if you have it in stock, and if you do not, they would like to know how soon you will have it. Any company that ships a product that they do not produce themselves runs into this problem consistently, and often enough you will need to connect you systems to your distributors to get a virtual inventory to keep your customer happy.
The Problem of Real-Time Inventory
Let us call our fictitious company Alpha Parts. They sell computer paraphernali, thousands of items like printers and mice and laptops, and procure their inventory from the following five warehouses: MicroBell, JME, DataTech, Xenns and LargeDeutsche.
Now, as simple as this model seems from a business perspective (maybe it is more complicated than I think) it poses a very interesting technical challenge in order to display product availability on the Alpha Parts website of items that have not physically entered their inventory. How do we know how many Cannon X15 printers MicroBell has? Or the amount of Microsoft Explorer mice that is in the Xenns warehouse?
Alpha Parts could request daily files of inventory availability from their partners, but that data could become stale in minutes. It turns out that each of these partner warehouses has XML web services that can be called individually via HTTP. Now, Alpha Parts need has an interface into individual product inventory per warehouse, but needs to turn that data into a usable system that aggregates and gives meaning to these numbers to their customers.
And here lies the problem: Real time on the web. We have the following challenges: multiple long running real time method calls to a third-party service over the internet, displaying results that return at different times and handling unresponsive services.
Solution
One of the lead engineers at Alpha Parts proposes solving these challenges by using the Service Gateway pattern in the middle tier and an ASP.NET compatible Ajax component on the front end. Let us take a look at the Service Gateway.
The Service Gateway pattern is a repeatable design that “encapsulates the details of connecting to the source and performing any necessary translation.” Here is a logical overview of the pattern.
Figure 1
The web application sends its request to the Gateway. The Gateway is then responsible for translating the request into the proper format to send to the External Service. After the response comes back from the external service it is returned to the gateway where it is then translated back into a representation that the application understands. It is also at this point where the gateway can use the persistence layer for storage or retrieval of data.
The next figure is a UML breakdown of the gateway layer.
Figure 2
Class Breakdown
Gateway – responsible for providing coordination and translation for calling the external service
PartnerInventory – object that describes products availability at a particular vendor
PartnerInventoryCollection – object representing a collection of PartnerInventory objects
RealTimeInventoryAccess – this is an existing class that handles the actual post to the services
GatewayPersistence – responsible for persisting and retrieving data from cache or the database – this could also be used to perform an algorithm to decide what stock results are active enough to stay in memory cache and which should persist to the database
GatewayDataAccess – responsible for physically persisting and retrieving data to the database
The pattern is straightforward enough and only really gets complicated depending on the extent of logic that is desired in the persistence layer.
Each time a method is invoked from the Gateway to RealTimeInventoryAccess (and hence, the external service itself) it will be done with an asynchronous method. The following figure shows the idea behind this, not the exact code.
Listing 1
ThirdPartyInventoryDelegate third =
new ThirdPartyInventoryDelegate(RealTimeInventoryAccess.GetInventoryByVendorsAndItemsCode);
IAsynchResult synchResult =
third.Invoke(parameter, new AsychCallback(method), third);
synchResult.AsynchWaitHandle.WaitOne(time, true);
The Alpha Parts engineers want to ensure that the web application continues processing while the web services are being called; so they propose calling each web service asynchronously in order to return information to the Gateway object as the services returns. This way they can be run through the persistence layer sooner. Each asynchronous method call is also done with a timeout value in order to prevent the HTTP post from waiting on the default timeout which could be too long (notice the WaitOne in the above listing). This will also enforce our own time limits for those remote method calls.
Being as such, if a method was called at 8:00:01 AM and method two was invoked right after that, if the first service call took longer to return, the second call could already be done processing the service XML and have handed the data back to the Gateway for the persistence layer. It basically allows the multiple calls to return on their own time and not queue up behind each other so that there are not wasted cycles.
The Ajax capable front end is another key facet to this design coming to life.
Alpha Parts can use an Ajax component, like ComponentArt’s CallBack. This control allows you to dynamically refresh an HTML region with JavaScript, but control it all from the ASP.NET server side code. This is a great benefit because it means they would not have to write their own JavaScript. A third party control also ensures that it has been tested, debugged and run on multiple platforms and browsers.
When a product page loads on the Alpha Parts website, the full page will load except for the real time html region. The CallBack component will call the page class which will check with the Gateway and its persistence engine to see if there is current inventory information available. If it is available, those objects are returned to the page and bound to the CallBack control. If they are not available from persistence, they are sent out to the external service(s) and the CallBack control will display a “loading” icon. The user is then free to use the rest of the page and as soon as the Service Gateway is done with its work its return objects will be bound to the CallBack control.
Conclusion
In this way, the middle tier will be working asynchronously to retrieve inventory information from multiple services and the web application will work asynchronously to display the data it will have to occasionally wait for.
References
Jim Tyhurst, Services That Reach from the Inside Out. Dr Dobbs Architecture and Design World 2006
Delegate the Work
A staple of any good management class is pounding into young executives’ heads that they should delegate when possible. These gurus of commerce do not say to always delegate because it’s obvious that expert knowledge should sometimes directly handle a task or project. But the premise is solid. And the premise applies to our world of software.
The .NET Framework provides us with a staid and true mechanism for creating delegates and wiring up events. It’s a powerful platform provided for free to us, so taking advantage of it is something a developer should aspire to do without much hesitation. Events are brothers-in-arms with delegates. They work together so smoothly that you might not even realize that events in the Framework and Windows Forms applications are actually using delegates behind the scenes.
Delegates are useful to implement function pointers or callbacks. Here are the basics of a delegate: Defining a delegate lets you invoke other functions that match the definition of the delegate. Right – what does that mean?
First off, a delegate is really a class. It derives from System.Delegate (really, it could also derive from System.MulticastDelegate, but we’re trying to keep thing simple here). So, you can define a delegate and then call it like a method. See Listing 1.
Listing 1 – Define a delegate
Public delegate bool CookDinner(string MainCourse);
So, what does this get you? First notice that the delegate looks like a method definition with a return type and method parameters. That should feel pretty comfortable. But, like I mentioned above, this is actually getting created as a class, so under the hood it is much more than a method. Now that we have this delegate defined we can use set it up for use. See Listing 2.
Listing 2 – Setup the delegate
CookDinner cook = new CookDinner(CookingTacos);
Private bool CookingTacos(string Meat)
{
if(Meat != “vegetable”)
{return true;}
else
{return false;}
}
Note that when we initialize the instance of our delegate, CookDinner, with the variable cook we are passing in a method that matches the delegate’s definition to the constructor. This is very important. All it takes to instantiate an instance of the delegate is a logical pointer to a method. Now take a look at Listing 3 and you’ll see how the delegate is used.
Listing 3 – Use the delegate
FeedTheFamily(cook); //pass in the delegate
Private void FeedTheFamily(CookDinner cookIt)
{
cookIt(“Beef”);
}
This helps us decouple a specific action from each method. Here, we can pass in our delegate to FeedTheFamily and that method is then able to call the method we already defined. So now if we decide that FeedTheFamily needs to cook something else, we change the method that is passed in the CookDinner constructor.
Events owe their livelihood to delegates. Before reading this you should understand that delegates allow you to call a method indirectly through the delegate construct. The focus in discussing events here is not to go into an in depth analysis of invoking and handling different events in Windows Forms and the .NET Framework. Instead, the focus is to see how delegates and events work together and how you can create and use them to add flexibility and maturity to any type of application. Let’s take a look at a fresh example. This example handles events for when a record is read from a database. See Listing 4.
Listing 4 – Define a new delegate
Here we follow the traditional event programming idiom of passing the object reference of the sender along with an object inheriting from System.EventArgs that contains specific event information.
Listing 5 – Define the Event
Here we have an event and a method to raise the event. Both of these are internal to a class named Transform. The event is defined in terms of the delegate type. And the method OnRecordRead is called internally, which in turn raises the event up to the event. Let’s now see how a class hooks this up in Listing 6.
Listing 6 – Application using the event
Now we’re really getting somewhere. What you see in Listing 6 is a class named Client. Inside of Client a new instance of the class Transform is instantiated. Next, a handler is wired up to the RecordReadEvent that matches the delegate type of RecordReadEventHandler. And finally, the method HandlReadRead actually handles the information, or events, that are published. In essence, Client is acting as a subscriber to the information that Transform is publishing. Listing 7 below ties these last three diagrams all together.
Listing 7 – Tying it all together
To summarize this, here are the major parts.
· Delegate definition
· Event definition
· Event publishing
· Event subscription
· Event Handling
And what is the beauty of all this? The fact that it’s easily extendable and usable in your ASP.NET applications, console apps, utilities and smart applications makes it so. It goes way beyond Windows Forms and can add loose coupling and flexibility which is something that object oriented software should strive for.
Not All Interfaces Are Built the Same
In my last article I described using composition in the design of an object based system. In that article I included a simplified UML class diagram of some work I did to a fictitious Product object to display the use of composition. Please see Figure 1 below. At the top of that diagram sits the class ProductBase. It is an abstract class (a class that has abstract methods and cannot be instantiated). But why is it abstract?
Figure 1 – Product UML
Let us first ask what could the class be marked as if it were not an abstract class? Here, there are two options. One, it could be a concrete class and two, it could be an interface. Let us look at the concrete class first.
A concrete class is any class that is not abstract; it is just a class. The following code snippet contains a concrete class followed by an abstract class.
Listing 1 – Concrete and Abstract
public class StockStatus
{}
public abstract class ProductBase
{
abstract public StockStatus InventoryStatus{get;};
}
When a class is concrete that means the only way to extend the class is by inheriting from it. That is often referred to as implementation inheritance or class inheritance because you are in essence inheriting all of the code and logic that went into the base class. That is not something I wanted to do with the Product object because it blows up encapsulation and is very inflexible.
The second option was to use an interface. Here, we would define an interface and then have ProductBase implement that interface. In the future, we could then substitute any class that implemented the interface.
Listing 2 – Using an interface
public interface IProduct
{
int GetNumberInStock();
}
public class ProductBase : IProduct
{
public int GetNumberInStock()
{
return 3;
}
}
In my first go around, this is basically what I had. Of course, that is why design reviews are important. It was pointed out by a coworker during a review that using an interface in this instance does not buy you anything more than using an abstract class, and if an abstract class were in fact used, we could mix in a little bit of implementation. Sounds good right? At first I did not like it at all.
“That breaks encapsulation!” I bellowed across the table, and let it reverberate off the walls and deaf ears. No one wanted to hear it. Why? Because using an abstract class here was simply a better design decision.
In this instance, a Product, no matter how many times subclassed, is a product. It has properties and some core methods. So in our abstract class we defined all of our entity properties implementation but left the “Load” (of data) methods as abstract so that the implementing class could define those. It ended up as an unintentional use of the template method, which is a good side effect of paying attention to your design. I believe that the decision is a mix of the best of both worlds.
Summary
We now have a good abstract class, which behaves as a well defined interface, plus when it comes time to substitute in another class of the same type, we have a lot of the plumbing already there. If we had used an interface it would mean we would have to rewrite a lot more code. This minimized our code creation and maintenance, but still keeps us in good object hierarchy.
Wait…Compose Yourself First
Of course, I am not the only one. If you are familiar with our friends, the Gang of Four, you have already heard this mind-bending concept. Make your objects connect to each other via well defined interfaces and hide their implementation. This is a sound, modern software practice. In fact, I just spent four days this past summer listing to speakers take composition for granted at the architectural level. They were assuming (not all of them of course) that composition and abstraction is a skill that is taken for granted by most developers. We know, being the folks in the trenches, that this is not always the case.
Favor Composition
Let us look at some simple composition here and discuss what the big deal is all about. To start, here are what I believe to be the three most important and beneficial things about using composition.
- Black Box design (where inheritance is white box design)
- Does not break encapsulation
- Relationships can be defined at runtime
Black box design means that the client using the object does not know the internal operations. This is in contrast to inheritance, where the class often knows the internals of its super class. Not breaking encapsulation is as good a reason to use composition as any. After all, encapsulation of operations and data is one of the main reasons to use object orientation. And lastly, “relationships can be defined at runtime” means that other objects can be plugged into, or composed with, other objects while the program is executing. This is a common use of the Strategy pattern, where an algorithm is set to the class at runtime.
Looking at an Example of Composition
Below, you will see a snapshot of part of a fictitious product component. ProductBase is composed of StockStatus, which in turn is composed of PurchaseOrderLine and IRunRate. Here, StockStatus does not know about the implementation of IRunRate, it only knows IRunRates interface. Here, we can then substitute any other object of type IRunRate into StockStatus and it would be none the wiser. You could of course, change behavior by having StockStatus be aware of its algorithms and change depending on what it is composed of – but that is not taking advantage of composition.
Figure 1 – UML Diagram
PurchaseOrderLine is the next object. Although StockStatus is not connected to an abstract class or “interface” type, the public methods and properties of PurchaseOrderLine make up its interface. So, again, StockStatus only knows about a well defined interface.
Conclusion
It is important to look at your design and try to understand the moving parts. These will let you know what the system will be composed of. In my next article, I will talk more about identifying the objects that make up your system, as well as why this design used an abstract class at its base and built upon it with composition.
Object Relational Mapping in ASP.NET 2.0
Introduction
The task was simple and sounded like a decent technical challenge and an interesting opportunity. Build an ASP.NET 2.0 with SQL Server 2005 transactional website that the financial industry can use to list special events and webinars so traders and investors can find it all in one location. I worked with the business owner and came up with the high level requirements. They are listed next and will look familiar to most of you.
1. Provide ability for users to register.
2. Allow registered users to list their events and webinars.
3. Allow registered users to perform CRUD actions to entered data (create, read, update, delete).
4. Provide administration interface for CRUD to all application data.
5. Display all events on the website in a format that allows sorting.
Of course, there were more requirements than what is listed above, but this is the core that we focus on moving forward in this article.
I have my own technical requirements that I bring to projects I lead, namely, that it should be as object oriented as possible and utilize the tools and technology available. ASP.NET is object oriented itself, so extending this concept into the other layers of the application is logical and advantageous. The second requirement is that the design should not only promote code reuse, it should provide for it. Repetitive code and functionality is a waste and a design “smell” that I try to avoid.
This project is the type that could easily end up with repetitive and hard to maintain code, especially in the data layer. Let us take a look at the options for data access. First, we could write inline SQL for all data access. We can rule that one out easily, as it ends up being difficult to maintain and makes OOP concepts difficult to apply. Let us not jump in the tank with that octopus.
The second option is to use stored procedures and wrap them with their own methods. This is without a doubt the most popular way to build a data driven solution with any of the .NET languages and technologies. If you ask any group of developers if they use stored procedures for their data access at any point in time you will see that four out of five reply with an affirmative. Take that to the next logical step and ask why they use stored procedures; the answer is almost consistently – (a) it is faster because it is compiled and (b) that it is more secure. I will accept (b) as a technically sound and savvy answer, but will question (a) all night long. Without rehashing this impassioned argument, I will simple say you can get the speed of stored procedures within .NET without writing a single stored procedure. Plus, you can get that with a better, cleaner and more object oriented manner.
OR Mappers
What is Object Relational mapping? In a nutshell, it is a technique to provide automatic retrieval and persistence of data. Usually this involves using a configuration file, often in XML, to map fields in your custom coded objects to fields and tables in a database. In this way the OR Mapper can then take ownership of the best way to retrieve, update, insert and delete data and you can focus on building the application and not mess with the plumbing.
Most professional developers use third-party components at some time and OR mapping products are an example of the acceptance and reliance on these types of components. The reality of our work is that almost every application has to touch a database and this data access work is error prone, tedious and honestly, just plain boring after a while. This type of work lends itself to mistakes. I am reminded of the classic software developers axiom, “if you can reduce risk, then do so.” This is one reason to use an OR mapper.
Another OR mapper advantage is the speed of development. Using an OR mapper can drastically reduced the amount of code that needs to be written and debugged, plus it can quicken how you develop. If you are mapping data directly to your objects, essentially making them entity objects, there is not data conversion between Datasets, data readers, structs or anything else. This reduces the complexity and makes working with your data essentially the same as working with your objects. Now your focus is on your domain model and not how ADO.NET is doing this or that task. Please note that I am not saying that understanding ADO.NET is not important – you should understand these concepts to be a productive and knowledgeable developer – but now that you understand the core concepts you can step beyond it and really take advantage of this knowledge.
True OR mappers, which I consider different than code generators, do all their database access dynamically. So, they are not generating files with code in them, and they are not using stored procedures. In the .NET world, the mapper will do all its database access using parameterized queries, which as controversial as it may sound, are just as fast as stored procedures. Thus, you now have the flexibility of dynamically generated SQL with the speed of a stored procedure.
Use of an OR mapper also provides a level of abstraction between your code libraries and the data source. Let us say that you are using MS Access as your application data source and you are using an OR mapper. You can now easily switch from MS Access to SQL Server 2005 without too much trouble because you do not have anything hard coded into your application that ties you to a platform. Extrapolate this out and you can migrate from Oracle to SQL Server or Access to MySQL, or really any way you wish.
The biggest concept to understand here is that the OR Mapper is providing flexibility. Flexibility in how you write your objects, flexibility in how you spend your development time and flexibility in what your data source is. And of course, they are fast at the same time.
Different OR Mappers
There are many different OR mappers available. The three products that I consider when thinking about the object relational mapping category are NHibernate, LLBL Gen Pro, RapTier and Wilson ORM.
NHibernate is the open source port of the popular OR mapper Hibernate for java. I am not a java developer so I can not speak to how good of a port it is. I have not used NHibernate myself, mainly because I have found the documentation of the product to be poor so far. There is a very active community around this product, but for my project I did not want to participate in their project, I wanted to focus on building mine. I have read and heard of success stories from colleagues along with their accompanying horror stories with NHibernate. I do consider NHibernate to be a true mapper because it does not generate code for the developer to manage. It does all its work dynamically once configured.
The second mapper is LLBL Gen Pro, which comes with its own environment for mapping objects with database tables and fields. This product does generate code files, so it is not something that I wanted to use this time around.
The third product is called RapTier. I have used this on a couple different projects earlier this millennium with success. RapTier does create code files though, so you have to maintain those and is something I would not consider doing now. But at the time, I experienced this product to be a great time saver because it allowed me to focus on the application and not the data access. The company also provided good support and an aggressive price.
The last product is WilsonORMapper and is ultimately what I decided to use on this project.
Why WilsonORMapper?
When push came to shove the choice for this project really came down to the merits of WilsonORMapper versus NHibernate. They are the two true, non-code generating mappers that I investigated and each had their own pluses and minuses. I choose WilsonORMapper for a couple key reasons; starting with that Paul Wilson, the creator, provides direct support for the product and the support site includes an active user forum where other users help each other and share advice and support. Beyond this, Wilson provides staid examples explaining how to use the different features of WilsonORMapper at a very good price.
Compared to NHibernate, these features were much more important to me during this project than the open source community behind NHibernate. I made the conscious choice to focus on a tool that could help me build my project as opposed to contributing to the tool’s project and would have support behind it.
Domain Objects
Part of the elegance of using an ORM product is that you can continue to use the domain (or call them entity) objects that you might design before event deciding on using ORM. This allows you to keep your custom objects and other steps towards a domain model and OOP principles intact while at the same time simplifying your database access. See Figure 1 for a part of the domain model used on this project.
Figure 1
In the above figure you can see part of the domain model. Here, we have objects describing a Listing, Feedback, Owner, Event and an interface for Event named IEventDetail.
Configuration File
The configuration file is what ties together the database tables and fields with your objects as shown in Listing 1.
Listing 1
<?xml version="1.0" encoding="utf-8" ?>
<mappings version="4.2" defaultNamespace="">
<entity type="Owner" table="Owner"
keyMember="Id" keyType="Auto" sortOrder="LastName ASC" autoTrack="false">
<attribute member="Id" field="OwnerId" alias="Id" />
<attribute member="FirstName" field="FirstName" alias="FirstName" />
<attribute member="LastName" field="LastName" alias="LastName" />
<attribute member="Street" field="Street" alias="Street" />
<attribute member="Street2" field="Street2" alias="Street2" />
<attribute member="Number" field="Number" alias="Number" />
<attribute member="City" field="City" alias="City" />
<attribute member="State" field="State" alias="State" />
<attribute member="Postal" field="Postal" alias="Postal" />
<attribute member="Country" field="Country" alias="Country" />
<attribute member="Company" field="Company" alias="Company" />
<attribute member="Email" field="Email" alias="Email" />
<attribute member="UserName" field="UserName" alias="UserName" />
<attribute member="Salt" field="Salt" alias="Salt" />
<attribute member="PasswordEncrypted" field="Password" alias="Password" />
<attribute member="Role" field="Role" alias="Role" />
<relation relationship="OneToMany" member="Listings" field="OwnerId"
type="Listing" alias="Listings" lazyLoad="true" cascadeDelete="true" />
<relation relationship="OneToMany" member="Events" field="OwnerId"
type="Event" alias="Events" lazyLoad="true" cascadeDelete="false" />
</entity>
The configuration file is in XML, so the hierarchy of data is simple to read and just as easy to understand after you use it for a short while. The entire file is wrapped in the mappings element and each table-to-object relationship is defined in an entity element. The Listing 1 example above ties the object Owner to the table Owner. It sets the object key, Id, to the tables’ primary key via the keymember attribute. It then sets the default sort order and a attribute named autoTrack which lets the ORM framework know whether or not to watch this object and perform SQL changes on its own.
Each property of the object is then mapped to a database field via an attribute element and member attribute.
Notice the element relation. This provides foreign key relationships to other tables. In this example the field OwnerId in the table Owner is linked to the table Listing with a synonymous field name. From here we can set the Listing object to be lazy loaded inside of the Owner object. So, to summarize this, each object is mapped to a table in the configuration file. Furthermore, a related object can be lazy loaded as a property in another object via foreign key relations.
ObjectSpace Manager
The ObjectSpace object is part of the WilsonORMapper libraries and is the main coordinator that is used by the developer to access data through the framework. It is best to only have one instance of the ObjectSpace object in an application. Doing so will help manage concurrency in the application between the data source and the mapper and secondary; the object loads up the xml configuration file from disk. So, obviously you do not want to repeatedly read from disk or recreate the object over and over. See Listing 2 for an example of how to create the object, in our case and by example from Wilson, the object is static and named Manager.
Listing 2
public class Global
{
private static ObjectSpace _Manager;
public static ObjectSpace Manager
{
get
{
if (_Manager == null)
{
CreateORMapper();
}
return _Manager;
}
}
private static void CreateORMapper()
{
string mappingFile = System.Web.HttpContext.Current.Server.MapPath("~/trader.config");
_Manager = new ObjectSpace(mappingFile, ConnectString, Provider.Sql2005);
}
}
Select
Let us take a look at a method that retrieves data from our source by doing a simple SELECT in Listing 3 below.
Listing 3
public Event GetEvent(int Id)
{
return (Event)Global.Manager.GetObject(typeof(Event), Id);
}
This method simply returns a filled Event object via the Id passed into the method. We use the GetObject method on the Manager object, which is of type ObjectSpace, and tell it the type of object to return. The mapper then knows what table the object type is mapped to and does the translation for us. The GetObject method can also then take in the parameter here, which is simply doing a query via the primary key setup in the configuration file.
Notice here how everything is strongly typed. The code does not have to know anything about ADO.NET or even the internals of the Event object. The mapping loads the right result set fields into the created Event object properties and fields.
On a side note, it is a matter of preference if you map your table fields to properties of the object or fields. The more draconian OOP bylaws would say that if you’re setting data in an object it should be via properties. But here, the mapper can access everything inside of the object anyway – so, it is a matter of preference.
Returning one object is simple, but the world works in large numbers, so let us look at returning a collection of objects. See Listing 4 below.
Listing 4
public IList GetEvents(string sortOrder)
{
ObjectQuery oq = new ObjectQuery(typeof(Event), "", sortOrder);
ObjectSet allEvents = Global.Manager.GetObjectSet(oq);
return allEvents;
}
The GetObjects method of the Manager object returns a collection object called an ObjectSet, which is part of the WilsonORMapper libraries. Being a well behaved collection it implements the IList interface. So our GetEvents above can be typed to IList to add some flexibility.
Insert, Update and Delete
Doing the other parts of the CRUD cycle (create, update and delete) are very similar. Listing 5 below shows an insert and Listing 6 shows an update. These are all working against that same Event type.
Listing 5
public void Insert(Event theEvent)
{
Global.Manager.StartTracking(theEvent, Wilson.ORMapper.InitialState.Inserted);
Global.Manager.PersistChanges(theEvent, Wilson.ORMapper.PersistDepth.ObjectGraph);
Global.Manager.EndTracking(theEvent);
}
Listing 6
public void Update(Event theEvent)
{
Global.Manager.StartTracking(theEvent, Wilson.ORMapper.InitialState.Updated);
Global.Manager.PersistChanges(theEvent, Wilson.ORMapper.PersistDepth.ObjectGraph);
Global.Manager.EndTracking(theEvent);
}
The basics of this operation are that the methods first call a WilsonORMApper method called StartTracking on the Manager object and then does the persistence. StartTracking lets the mapper know that this object and its associated row in the database are going to have work done to it. I am not sure if WilsonORMapper locks the row then or not, but it does add safety to the operation. Part of StartTracking is telling the mapper if we will be inserting and updating data. Then we call the PersistChanges method and lastly end our tracking of that object and database row.
Performing a delete is very similar and can be seen in Listing 7.
Listing 7
public void Delete(Event theEvent)
{
Global.Manager.StartTracking(theEvent, Wilson.ORMapper.InitialState.Unchanged);
Global.Manager.MarkForDeletion(theEvent);
Global.Manager.PersistChanges(theEvent, Wilson.ORMapper.PersistDepth.ObjectGraph);
Global.Manager.EndTracking(theEvent);
}
The only addition with the delete is we call MarkForDeletion which is another trigger letting the mapper know what we are about to do to that object and its data.
Lazy Loading
An aspect of object oriented programming that is simpler to do with an object relational mapper is lazy loading one object type from within another. For example, if we want to load up the Owner object of an Event object, for instance, the company hosting the event, we can write our lazy load property in the Event object and then simply create an Owner object with the owner id key returned from our Event object load. In this way your object model can grow and objects maintain a high level of encapsulation.
Conclusion
An object relational mapper is a powerful tool to use and can save days – and possibly weeks depending on the size of the project – of tedious coding and debugging. Within a short time you can get up and running and use the object model that you created for the project without having to rework a lot to run stored procedures or other ADO.NET queries. In the end you can focus on the core business logic part of the application and consider the mapper and your data layer as plumbing that came with the house. WilsonORMapper simply makes this much easier with better support than other free or complicated OR mapping solutions out there.
Comments (1)









