Let's go with the most basic example and assume that we want to map a class directly to a table in our database. In the following example, we're going to create a simple mapping between a Product object and the Northwind Products table.
Prerequisites:
Visual Studio 2005
NUnit or Zanebug
Sql Server 2000 or 2005 with the Northwind database
Create a new Visual Studio C# Class Library project (Elementary works with both VS2003 and VS2005)
Add references to the following dlls:
Adapdev.dll
Adapdev.Data.dll
Elementary.dll
nunit.framework.dll
Add the following Product class to your solution:
using System;
using Adapdev.Text;
using Elementary.Attributes;
namespace Elementary.Northwind.Samples.Attributes.SimpleExample
{
[ElementaryClass]
public class Product
{
[Persist]
public int CategoryID = 0;
[Persist]
public int ProductID = 0;
[Persist]
public string ProductName = "";
[Persist]
public int SupplierID = 0;
public override string ToString()
{
return StringUtil.ToString(this);
}
}
}
This is a very simple Product representation that maintains the product name, id, and the ids of its supplier and category. In later examples, we'll demonstrate more complex mappings.
In your AssemblyInfo.cs file, add the following:
using Elementary.Attributes;
[assembly:ElementaryDatabase(Name="Test",
ConnectionString="Data Source=localhost; Initial Catalog=northwind; User ID=sa; Password=; Trusted_Connection=false;",
OledbConnectionString="Provider=sqloledb;Data Source=localhost; Initial Catalog=northwind; User ID=sa; Password=;")]
We have just created a database reference for the Northwind database.
Add the following unit test to your solution:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Transactions;
using Elementary;
using Elementary.Northwind.Samples;
using NUnit.Framework;
namespace Elementary.Northwind.Samples.Attributes.SimpleExample
{
/// <summary>
/// Summary description for Test.
/// </summary>
[TestFixture]
public class Test
{
[TestFixtureSetUp]
public void SetUp()
{
Elementary.Clear();
Elementary.LoadAssembly("Elementary.Northwind.Samples.dll");
}
[Test]
public void GetCollection()
{
// Retrieves the mapping via object type
IObjectMapper<Product> mapper = Elementary.GetIObjectMapper<Product>();
List<Product> al = mapper.GetCollection();
Assert.IsTrue(al.Count > 0, "No products loaded.");
Assert.AreEqual(77, al.Count, "Not all products were loaded.");
Console.WriteLine("Loaded {0} products.", al.Count);
Console.WriteLine("\nFirst product:\n{0}", al[0]);
}
[Test]
public void GetObject()
{
// Retrieves the mapping via object type
IObjectMapper<Product> mapper = Elementary.GetIObjectMapper<Product>();
// Retrieve product #1
Product product = mapper.GetObject(1);
Console.WriteLine(product);
}
}
}
Run the test. using either the test framework GUI (i.e. Zanebug GUI or NUnit GUI) or within VS.NET using TestDriven.NET. You should see the following output:
Properties for: Product CategoryID(System.Int32): 1 ProductID(System.Int32): 1 ProductName(System.String): Chai SupplierID(System.Int32): 1
Elementary went against the database, retrieved the product with id #1, and returned it without you having to write one line of SQL! Granted, it's not that impressive...you're probably thinking I could have typed just as much writing my own SQL - but we're just scratching the surface. Also, you haven't embedded SQL into your code, which gives you much more flexibility (as you'll see later) and behind the scenes Elementary is managing several advanced capabilities.
Let's continue by adding an additional unit test...
Add the following unit test to the existing Test class:
[Test]
public void GetCollection()
{
IObjectMapper<Product> mapper = Elementary.GetIObjectMapper<Product>();
List<Product> products = mapper.GetCollection();
Assert.IsTrue(products.Count > 0, "No products loaded.");
Assert.AreEqual(77, products.Count, "Not all products were loaded.");
Console.WriteLine("Loaded {0} products.", products.Count);
Console.WriteLine("\nFirst product:\n{0}", products[0]);
}Without any modifications, we were able to retrieve all products in the database - simply by calling the GetCollection method.
Great you say...but what about creating new products? Let's see how much effort it requires...
Add the following unit test to the existing Test class. We're going to wrap it in a transaction and roll it back so that we don't muck up Northwind:
[Test]
public void SaveObject()
{
IObjectMapper<Product> mapper = Elementary.GetIObjectMapper<Product>();
// get the current total number of products
int count = mapper.Count;
Product product = new Product();
product.CategoryID = 1;
product.ProductName = "Test Product";
product.SupplierID = 1;
// Run in a transaction and rollback so that database changes aren't saved
using(TransactionScope scope = new TransactionScope())
{
mapper.Save(product);
// get the modified total number of products
int newCount = mapper.Count;
// make sure the object was added
Assert.AreNotSame(count, newCount, "Object wasn't saved.");
}
}As you can see, again we made no modifications to our code, but were immediatlely able to save a Product to the database simply using the Save method.
If you wanted to make changes to a Product, you could do so and then call Update.
To remove it, simply call Delete.
So far we've only covered the most basic of CRUD (Create, Read, Update, Delete) operations. Elementary is capable of much, much more such as retrieving all Products, their associated Suppliers and Categories in one call; caching all objects; extending and inheriting mappings, etc. Once we explain the basics of mapping, we'll dive into these more advanced capabilities.