The following section explains how to set
up a project and create a mapping for a simple business layer.
The sample can be found in the {Genome
installation folder}\Samples\GettingStarted\Step1 folder.
To set up a solution, first create a C# class library project, which will contain the business classes of the business layer to be mapped. In our example, we will call our business layer Business:

New Project dialog for creating the business layer
Create an assembly reference to the Genome runtime API (TechTalk.Genome.dll found in {Genome installation folder}\bin) for the project in order to derive the business class from Persistent, a Genome base class, if desired (deriving from Persistent is not mandatory but recommended; more on that later):

The Genome runtime API TechTalk.Genome.dll can be found in the Genome installation folder under the \bin directory
The first class we will implement is called Product:
using TechTalk.Genome;
namespace Business
{
public abstract class Product : Persistent
{
public abstract int Id { get; }
public abstract string Name { get; set; }
public abstract decimal Price { get; set; }
public Product(string name, decimal price)
{
Name = name;
Price = price;
}
public override string ToString()
{
return Name;
}
}
}
Deriving Product from Persistent, a Genome base class, is optional but recommended, as it provides the following benefits:
Product specifies three scalar properties: Id, Name and Price. As these properties will be mapped to fields in the database, they are left abstract. During business assembly compilation, Genome compiles a concrete implementation for Product with the necessary data access code, which is called the object proxy. During runtime, Genome object proxies for Product are instantiated whenever you expect a Product instance. However, you always work with the interface of abstract class Product.
Also note that only a getter, not a setter, is specified for Product.Id. This is because the Id in this case is generated by the database and should not be settable through .NET code. Genome supports both identities generated by the database server as well as identities initialised by the .NET code on the client side.
Product also implements some simple business logic with a constructor and by overriding ToString(). Any additional methods and properties can be implemented on Product to represent additional business logic necessary.
After finishing this, the business layer project can already be compiled successfully without any errors.
To map the business layer with a Genome schema assembly, a Genome DataDomain project has to be added to the solution. This project type can be found under the Genome Projects node in the project types tree view when Genome integration has been successfully installed for Visual Studio with the Genome setup programme.

The Genome Project types can be found under the “Genome Projects” node in the project types tree-view of the Add/New project dialog in Visual Studio
In this example we will call the DataDomain Schema project Business.Mapping.
Next, a project reference has to be created for the DataDomain Schema project to the business layer project to be mapped, in this case the Business project we created previously.
The empty mapping file Class.xml initially added to the DataDomainSchema project can be removed.
Next, we map the persistent class Product, whose instances are to be stored in the database.
Genome’s forward engineering wizard can be used for this to spare typing; navigate to the source code of Product and right click on Product. In the Genome mapping context menu, select Map as root type:

Genome context menu in the C# source code editor
The forward engineering wizard of Genome creates a new file called Product.xml in the DataDomain Schema project with the following mapping information:
<?xml version="1.0" ?>
<Mapping xmlns="urn:TechTalk:TT.OODAL.XmlMapping">
<Using namespace="System" />
<Using namespace="System.Data.SqlTypes" />
<Using namespace="TechTalk.Genome" />
<Using namespace="TechTalk.Genome.Mapping" />
<Using namespace="TechTalk.Genome.Schema.Builder.Xml" />
<Using namespace="Business" />
<Type name="Product">
<RootInheritance/>
<PrimaryKey>
<Key>Id</Key>
</PrimaryKey>
<Sealed/>
<CodeGeneratedProxy/>
<Member name="Id">
<PersistentField/>
</Member>
<Member name="Name">
<PersistentField/>
</Member>
<Member name="Price">
<PersistentField/>
</Member>
</Type>
</Mapping>
A Genome mapping file has a structure similar to a C# source code file.
In the beginning, a number of <Using/> elements specify the namespaces that should be included by default to look up type identifiers.
The wizard has added the namespace Business to the end of the list so we can refer to the class Product without qualifying it with the full namespace.
The <Type/> element specifies the CLR type to be mapped, in this case Product.
The <RootInheritance/> element specifies that this type is the root class stored in the database. Base classes of Product are not stored in the database (Persistent, System.Object). The <RootInheritance/> element assumes the class name is the same as the table name by default, in this case “Product”. The table name can be explicitly renamed using the tableName attribute of the element.
The assignment of the class to a concrete database table is also called the extent provider of a mapped class in Genome.
The <PrimaryKey/> element specifies the persistent properties of the class used to identify an instance of the object in the database. Genome does not require the corresponding fields in the table to be specified as primary keys as long as there are no rows in the table with the same primary key values, although from a database point of view it is recommended to do so. Genome supports any number and type of primary key fields. If the primary key is composed of more than one field, a <Key/> element has to be added for each member.
The forward engineering wizard has already tried to deduce the appropriate member of the class Product for the primary key by matching for a name ending with Id. If the object identity properties are named differently, they must be registered manually in the mapping file.
As mentioned previously, in our example the primary key value should be generated by the database. To inform Genome of this, the persistent field mapping for Id has to be modified:
<Member name="Id">
<PersistentField NativeIdGenerator="true"/>
</Member>
Updated mapping in Business.Mapping/Product.xml
When the NativeIdGenerator attribute is set to true, Genome queries for the object identity when the object is first created in the database and updates object references (foreign key values) pointing to the new object afterwards with this value.
The specification of the primary key fields for a type stored in the database is also called the object identity provider of a mapped class in Genome.
The <Sealed/> element is used to specify that there are no derived types of this type stored in the same table. This informs Genome that it does not need to identify the concrete type of each row for this table, which is usually done with a type identity field (see Inheritance later). Note that <Sealed/> may only be specified for types mapped with <RootInheritance/>. Once a table holds polymorphic data, each derived type stored in the same table needs to specify a discriminator value.
The specification whether or not a table holds polymorphic results (and how to identify different types in the table) is also called the type identity provider of a mapped class in Genome.
This element has to be specified if you want to create instances of this class in your application. It tells Genome to generate a proxy implementation for this type which implements interception for update tracking and lazy loading.
All scalar members of Product (Id, Name, Price) are mapped with the <PersistentField/> element to tell Genome that these members are mapped to fields in the database. As with the extent provider, Genome assumes by default that the name of the property in the class is the same as the name of the field in the database. The field name can be overridden using the fieldName attribute of the element.
The element can also be extended with database schema information for the persistent field, e.g. the following mapping specifies the Price to be generated as decimal (10,2) in the database:
<Member name="Price">
<PersistentField Precision="10" Scale="2"/>
</Member>
Updated mapping in Business.Mapping/Product.xml
If no additional properties are specified, Genome assumes default values for each CLR type mapped (e.g. nvarchar(255) for String).
During runtime, Genome does not need the additional mapping attributes for the persistent fields. Mapping a field as <PersistentField/> is sufficient to map a property of the persistent class to the corresponding field in the database table.
However, Genome can generate a database create script when compiling the schema assembly. To enable this, a SQL create script name has to be specified in the DataDomain Schema project properties:

DataDomain Schema Project properties can be used to specify a SQL Server create script to be generated with each schema compilation
Once this is specified, Genome generates a SQL create script called Business.sql with each compilation of the DataDomain Schema project.
Finally, the DataDomain Schema Project can be compiled by choosing Build in the project context menu or rebuilding the whole solution. The Build Output window shows compilation information of the Genome DataDomain Schema Compiler ddsc.exe which is called after csc.exe builds the business assembly.
Any errors discovered during compilation are reported to the Error List. Double clicking on the error will navigate to the corresponding position in the mapping file where the error occurred.
Errors can be also seen in the build output window of Visual Studio where ddsc.exe prints out messages during compilation.
After compiling the DataDomain Schema project, the schema assembly with all its dependencies can be found in the build output directory of the project (in this case Northwind.Mapping.dll).
The database creation script can be found in the DataDomain project root directory after compilation.
| Introduction | Initialising and using a DataDomain |