
|
|
QUICK TUTORIAL By Priti Narang |
Introduction to NJDX OR MapperSoftware Tree's NJDX is a powerful, flexible, and easy-to-use object-relational mapping (OR-Mapping) product that simplifies and accelerates the development of .NET applications by providing intuitive, object-oriented access to relational data. Adhering to some well thought-out KISS (Keep It Simple and Straightforward) principles, NJDX supports complex object modeling, provides integration with popular databases and legacy data, and employs a highly optimized mapping engine. NJDX avoids code generation approach by employing a metadata driven programming model. NJDX has been tightly integrated with Visual Studio .NET and can be used with any CLR-based language, including C#, VB.NET, and J#.
Tutorial Objective
This is an introductory tutorial for new users of NJDX OR Mapper. NJDX makes a programmer's job easy by providing simple, intuitive and flexible APIs that take care of eliminating all the complexity of writing low-level ADO.NET/SQL code involved in integrating with relational data sources. NJDX helps you concentrate on business logic without worrying about the plumbing code. On our way to using NJDX, we’ll learn some new terminology that will help us understand NJDX better.
We will learn the basic steps that need to be followed to make our application up and running with NJDX. We will explore how classes are mapped to database tables and how an application can interact with a database without having to explicitly issue SQL commands.
The Development Process
There are three simple steps to use NJDX:
1. Define business objects (.NET classes). 2. Define/refine object-relational mapping. 3. Develop applications using NJDX APIs.
Before moving into the details of these steps let’s take a look at the object (domain) model that we’ll be using in this tutorial.
This model has a SimpleCompany class having one-to-many relationship with the SimpleDept class. This model also has a SimpleEmp class having one-to-one relationship with SimpleDept and SimpleAddr classes. All these classes belong to the namespace ABC. The field names follow a naming convention of ending with an underscore (_).
In the following discussions, the terms object model and domain model are used interchangeably. Step 1: Define business objects (.NET classes) of the domain model
NJDX does not impose any restriction in terms of how a class should be defined. Instances of any POCO (Plain Old CLR Object) can be persisted using NJDX. Here is an example of a class definition (ABC.SimpleCompany) used in the above domain model:
(1) A persistent class should be declared as a public class. NJDX does not require the persistent class to be inherited from any base class, nor does it require a persistence class to implement certain interfaces.
(2) Fields can be defined as either private or public.
(3) All persistent classes must have a default constructor with no arguments.
(4) For a private field, the public property should be defined.
Here is an example of another domain model class (ABC.SimpleDept):
Step 2: Define/refine object-relational mapping
Object-Relational Mapping File (ORMFile)
NJDX needs to know where to load from and where to store objects of the persistent domain model classes. This is where the NJDX mapping file (ORMFile) comes into play. The mapping file contains an object-relational mapping (OR-Mapping) specification, which defines the mapping information for all the persistent classes belonging to an application domain. The specification includes, among other things, table names, primary key attributes and object relationships. NJDX provides an innovative and declarative way of specifying human-readable and user-friendly object-relational mapping information based on a simple grammar. The mapping file can be generated easily using a text editor, NJDXStudio (add-in to Visual Studio), a modeling tool, or even programmatically. A mapping specification can correspond to only one database. While a mapping specification cannot span multiple databases, multiple mapping specifications can be defined for the same database. Also, an application can use multiple mapping specifications, where each specification may correspond to a different database.Here is an example of how we can define an OR-Mapping specification for the given domain model in a mapping file (e.g., Simple.jdx). Please note that NJDX, through it’s reverse-engineering facility, can automatically create a default mapping file and C# class definitions from an existing database schema.
Notice that the NJDX mapping file has a simple grammar and is easy to create, modify, and comprehend. There are no XML complexities.
(1)A CLASS specification encapsulates all the Object-Relational Mapping information for one class. The class name may include a namespace (e.g., ABC.SimpleEmp).
(2)A PRIMARY_KEY specification identifies the attribute (property) names whose combined values uniquely identify a particular object.
(3)A SQLMAP specification allows one to refine the mapping of a class attribute to the SQL column in one of the following ways - using a column name different from the attribute name, using an SQL datatype different from the default SQL data type for the attribute type, and allowing the column to be nullable.
(4)A COLLECTION_CLASS specification encapsulates all the Object-Relational Mapping information about a collection class. A collection is actually a pseudo-class; there may not be an actual class by that name in the program.
(5)A PRIMARY_KEY specification for a collection class specifies names of those attributes whose values are the same for all the objects in a collection.
(6)A RELATIONSHIP specification defines the mapping for a complex attribute referencing an object or a collection of objects. It keeps the application developer from worrying about explicitly initializing the "primary or foreign key" attribute values. BYVALUE keyword is used to indicate that, by default, the related objects should also be inserted, updated, or deleted with the containing object (CASCADE semantics). Step 3: Develop applications using NJDX APIs
In this step we’ll see how to develop applications using NJDX APIs. We will do some basic Insert, Update, Delete and Query operations using those APIs. The basic structure of the application using NJDX looks like this:
(1) Namespaces and Reference Assembly: To use NJDX APIs (belonging to the namespaces com.softwaretree.jx and com.softwaretree.jdx), we need to include NJDXCore.dll assembly as a reference library to the project. NJDXCore.dll can be found in the %NJDX_HOME%/bin directory.
(2)JXResource class provides the facilities to work with a mapping unit. A JXResource contains handles for JXSession and JDXS objects.
(3)JXSession interface defines transactional methods (like tx_begin and tx_commit).
(4)JDXS interface defines the methods that can be used by the application programmer for persistence of .NET objects and other relational services.
(5) jdxURL is used to specify locations for the object classes, the database tables, and the mapping specification that we’ll be using in the application. The easiest way is to provide these details to the JXResource constructor, which takes a jdxURL string as an argument. Here's how the ‘jdxURL’ used in the above example may look like:
jdxURL specification is typically provided in and read from a configuration file for ease of use.
Some examples of NJDX APIsMethod: insertSyntax: public void insert(Object object, long insertFlags, ArrayList insertDetails)
object - the object to be inserted in the database
insertFlags - specifies insert behavior (deep, shallow)
insertDetails - controls the insert operation in different ways.
The above code creates a SimpleCompany object (myCompany) and stores it in the database using the insert method. is will insert the myCompany object into Simple_Company table. Since FLAG_DEEP is specified, the associated SimpleDept objects will also be inserted in the database.
Method: querySyntax: public ArrayList query( String className, String predicate, long maxObjects, long queryFlags, ArrayList queryDetails)
className - name of the class whose objects need to be retrieved.
(1) This query retrieves at most 3 SimpleCompany objects in the state of CA (California). Since the query is done with a SHALLOW flag, none of the associated SimpleDept objects are retrieved. (2) This query retrieves only those SimpleCompany objects which have an associated 'Engineering' department. Since the query is done with a DEEP flag, all the associated SimpleDept objects in addition to the 'Engineering' department are also retrieved.
Method: updateSyntax: public void update(Object object, long updateFlags, ArrayList updateDetails)
object - the object to be updated in the database updateFlags - specifies update behavior (deep, shallow, positioned) updateDetails - controls updates in different ways.
The above code updates the myCompany object into the Simple_Company table. Since FLAG_SHALLOW is specified, the associated SimpleDept objects would not be updated.
Method: deleteSyntax: public void delete(Object object, long deleteFlags, ArrayList deleteDetails)
object - the object to be deleted from the database deleteFlags - specifies delete behavior (deep, shallow, positioned) deleteDetails - directed operation options, which may be used to control delete in different ways.
The above code deletes the record corresponding to the myCompany object in the Simple_Company table. Since FLAG_DEEP is specified, all the (BYVALUE) related SimpleDept objects will also be deleted.
Advanced Topics
NJDX is a versatile tool that provides many other advanced features. Some of them, which you might want to explore next, are:
API methods, other than the basic operations that we have covered:
· Named Query - NJDX provides the facility to define a named query with optional parameter markers. The named query can be defined once and used (executed) multiple times. Named queries can provide greater convenience, more flexibility, and better performance in many situations. The query will be executed by NJDX using a prepared statement for faster performance. The named query is automatically defined and executed for all the subclasses.
· InsertMany – This method is similar to "insert operation" but you may insert many independent objects with one call.
· Update2 – This allows bulk updates (in the database) of selected attributes of all objects of the given class, satisfying the given search condition (predicate) with the new attribute values.
· Delete2 - This allows bulk deletes (from the database) of all objects of the given class, satisfying the given search condition (predicate).
Other Interesting Features:
· Object caching - Provides super-fast access to business objects from high-performance memory cache.
· Stored procedure integration - Simple mapping specification for stored procedures. Flexible APIs supporting in, in/out, and out parameters. Automatic object-instantiations using stored procedure data sets.
· Class-hierarchies - Flexible storage options and polymorphic queries for objects belonging to a class hierarchy.
· Aggregate operations - Returns the aggregate value (COUNT, MIN, MAX, AVG, SUM) for the specified attribute of the qualifying objects. Enables easy data analysis.
· Path-expressions – Enables simple object-oriented specification of powerful query predicates involving referenced objects (e.g. “'Engineering' IN jdxObject.depts_.deptName” while querying over the SimpleCompany class). NJDX generates all the required SQL join statements to accomplish the task.
· Optimistic locking for concurrency control - Provides a faster and more scalable locking alternative to database locking. Especially useful for long-running transactions with minimal conflicting update operations.
· Forward-engineering of relational schema from object models.
· Reverse engineering of C# classes from existing schemas.
· JXResourcePool – Provides multiple JXResource components in an extensible pool and methods for thread-safe sharing of these components.
· NJDXStudio is an add-in of NJDX OR-Mapper related tools for Visual Studio. NJDXStudio provides a seamless integration of these OR-Mapping tools using a handy pulldown menu, a simple toolbar, and helpful wizards, allowing developers to easily perform such tasks as defining object-relational mapping, creating database schema, reverse-engineering C# classes from an existing database schema, and verifying OR-Mapping specification against live data.
· NJDXDemo is a utility program that provides a graphical front end for user input and invokes NJDX method calls and displays the results. We can use NJDX to easily verify an Object-Relational Mapping specification against existing data. NJDXDemo can also help in formulating ad-hoc query predicates, which can then be incorporated in the application programs.
To learn more about NJDX feature details, you can refer to a comprehensive user manual that ships with the software.
Conclusion
NJDX OR-Mapper makes the .NET application development task significantly simpler by presenting a more intuitive object-oriented view of the relational data. NJDX does it without any code generation and without imposing any new query language. This tutorial is just a quick introduction to NJDX and there is much more to NJDX than the mapping specification and calls like insert, query, update, and delete . NJDX provides many advanced features that let you fine tune it for the persistence needs of your application. Many helpful tools and utilities like forward-engineering and reverse-engineering streamline the development process. You can rely on NJDX not only for simple applications but also for more complex and high-performance
Resources
[2] NJDX development steps in a nutshell [3] KISS Principles white paper [4] Online demos [5] NJDX Petshop application report
You may download a free 30-day trial version of NJDX software from Software Tree's web site.
About the author
Priti Narang is a freelance software engineer based in the San Francisco Bay Area.
©2008 Software Tree, LLC; All rights reserved |
|||||||||