Thursday, February 18, 2010

Whitepaper - Designing Modular Smart Clients using Composite Client Application Guidance


I have created a whitepaper for Designing Modular Smart Clients using Composite Client Application Guidance. The paper provides architectural guidance for designing and implementing enterprise WPF/ silverlight client applications based on the Composite Application Guidance for WPF and Silverlight provided by the Microsoft Patterns & Practices group.
The Composite Application Guidance for WPF and Silverlight is a set of guidance designed to easily manage the complexities developing enterprise-level Windows Presentation Foundation (WPF) client applications and Rich Internet Applications (RIAs) with Silverlight. Composite WPF guidance helps design and build flexible client applications using loosely coupled, independently evolvable pieces that work together and are integrated into the overall application. This type of application is known as a composite application.
You can download the whitepaper from the below given links
Or


Friday, February 12, 2010

Data Access Layer in C# using Repository and Data Mapper – Part 4


The customer repository inherits the base repository and uses the data mapper instance for object creation. All the CRUD procedures defined in the first post of this series are called in this class. The query for accessing and persisting data in the relational model is formed in the Customer repository.
protected override BaseMapper<Customer, long> Mapper
{
    get
    {
        if (___Mapper == default(CustomerMapper)) ___Mapper = new CustomerMapper("CustomerIntId");
        return ___Mapper;
    }
}

public Customer GetById(long id)
{
    DbCommand command = ___Database.GetStoredProcCommand("usp_GetCustomerById");
    ___Database.AddInParameter(command, "CustomerIntId", DbType.Int64, id);
    return FindOne(command);
}

public void Insert(Customer entity)
{
    DbCommand command = ___Database.GetStoredProcCommand("usp_InsertCustomer");
    ___Database.AddInParameter(command, "FirstName", DbType.String, entity.FirstName);
    ___Database.AddInParameter(command, "LastName", DbType.String, entity.LastName);
    ___Database.AddInParameter(command, "Address", DbType.String, entity.Address);

    ___Database.AddOutParameter(command, "CustomerIntId", DbType.Int64, 8);

    ___Database.ExecuteNonQuery(command);

    Int64 customerIntId = (Int64)(___Database.GetParameterValue(command, "CustomerIntId"));
    entity.Id = customerIntId;
}

public void Remove(long id)
{
    DbCommand command = ___Database.GetStoredProcCommand("usp_DeleteCustomerById");
    ___Database.AddInParameter(command, "CustomerIntId", DbType.Int64, id);

    ___Database.ExecuteNonQuery(command);
}
I have uploaded the source code for the customer repository here.
[TestMethod]
public void can_insert_customers_into_db()
{
    ICustomerRepository repository = new CustomerRepository();
    var customerToInsert = new Customer { FirstName = "Prajeesh", LastName = "Prathap", Address = "BTM 2nd Stage, Bangalore" };
    repository.Insert(customerToInsert);

    var customer = repository.GetById(customerToInsert.Id);
    Assert.IsNotNull(customer);
    Assert.AreEqual<string>(customer.FirstName, "Prajeesh");

    repository.Remove(customer.Id);
}
Our final implementation looks like.

Data Access Layer in C# using Repository and Data Mapper – Part 3


Mapping the data elements in the domain model and relational model for the customer entity functionality is implemented as part of the CustomerMapper class which inherits from the BaseMapper created in the previous sample. The customer mapper class contains code to convert data between these data models.
public override Customer Construct(IDataRecord record)
{
    Customer customer = ConstructCommonData(record);

    int index = record.GetOrdinal("FirstName");
    customer.FirstName = record.IsDBNull(index) ? string.Empty : record.GetString(index);
    index = record.GetOrdinal("LastName");
    customer.LastName = record.IsDBNull(index) ? string.Empty : record.GetString(index);
    index = record.GetOrdinal("Address");
    customer.Address = record.IsDBNull(index) ? string.Empty : record.GetString(index);

    return customer;
}
The overridden Construct method is responsible for this data conversion. Once the data mapper is ready, we’ll use this in the repository for data access. The data mapper is not exposed outside the repository.
Creating the repository for the sample
Martin fowler writes:
"A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers."
Each entity in a domain layer defines a repository for data access operations. In our sample we have one entity (Customer). We’ll define a repository for the customer entity and write some test cases to demonstrate the functionality. The repository interface defines the CRUD operations required for our sample.
    T GetById(Key id);
    IList GetAll();
    void Insert(T entity);
    T Update(T entity);
    void Remove(Key id);
I have created a base repository class which will be used as the base class for entity specific repositories and implements the common functionality.
    protected T FindOne(DbCommand command)
    {
        T entity = new T();
        using (IDataReader reader = ___Database.ExecuteReader(command))
        {
            if (reader.Read())
                entity = Mapper.Construct(reader);
        }
        return entity;
    }

    protected IList Find(DbCommand command)
    {
        IList entityCollection = default(List);
        using (IDataReader reader = ___Database.ExecuteReader(command))
        {
            entityCollection = Mapper.ConstructCollection(reader);               
        }
        return entityCollection;
    }

The source for BaseRepository can be downloaded from this link
Next we’ll create the customer repository.

Thursday, February 11, 2010

Data Access Layer in C# using Repository and Data Mapper – Part 2


As mentioned in the previous post Data Mapper is a layer to hide database access from your domain objects. As a recommendation data mapper should not be exposed to the business logic layer. All calls to the data mapper should be routed via a Repository that should make use of the data mapper for object creation. The data mapper will have access to the domain model/ entities for object creation. In this post, we’ll see how to create a data mapper implementation in C#.
Before looking into the data mapper, we’ll create our first business entity, Customer. Every business entities in our sample inherit from a base entity that holds the common properties for key, versioning and tracking. The Customer entity is defined as
public class BaseEntity
{
    public T Id { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime ChangedDate { get; set; }
    public byte[] Version { get; set; }
}
public class Customer  :BaseEntity<long>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
}
All the business entities should be part of the domain model and is defined in separate assembly. In this sample, I have created a class library (DataMapper.DomainObjects) to define the business entities.
Once the entities are ready, we can work on the base mapper for all entities. For convenience I have defined the data mappers and repositories in another class library (DataMapper.ResourceAccess)



The Base mapper defines an abstract method Construct that should be implemented by all the entity specific mappers for mapping the relational database fields to the object properties. The constructcommonData method populates the baseEntity properties.

    public abstract T Construct(IDataRecord record);

    public IList ConstructCollection(IDataReader reader)
    {
        List entityCollection = new List();
        while (reader.Read())
        {
            entityCollection.Add(Construct(reader));
        }
        return entityCollection;
    }

    protected T ConstructCommonData(IDataRecord record)
    {
        T baseEntity = new T();

        int index = record.GetOrdinal(___KeyField);
        if (record.IsDBNull(index)) throw new ArgumentException("Failed to map the key field");
        baseEntity.Id = (Key)record.GetValue(index);

        index = record.GetOrdinal("CreatedDate");
        baseEntity.CreatedDate = record.IsDBNull(index) ? DateTime.MinValue : record.GetDateTime(index);

        index = record.GetOrdinal("ChangedDate");
        baseEntity.ChangedDate = record.IsDBNull(index) ? DateTime.MinValue : record.GetDateTime(index);

        index = record.GetOrdinal("Version");
        if (!record.IsDBNull(index))
        {
            baseEntity.Version = new Byte[(record.GetBytes(index, 0, null, 0, int.MaxValue))];
            record.GetBytes(index, 0, baseEntity.Version, 0, baseEntity.Version.Length);
        }        
        return baseEntity;
    }


Download the complete class file here
Next we’ll see how to implement the Customer data mapper for the Customer entity created in the sample.

Wednesday, February 10, 2010

Data Access Layer in C# using Repository and Data Mapper – Part 1


Data access is a popular subject in most of the applications. There are plenty of options on various data access techniques and frameworks that often create confusion in the minds of developers choosing the right approach or strategy for creating an effective data access layer. Two main things that should be considered while creating a data access layer are simplicity and reliability.
When creating an application with a domain model, one should consider the usage of a layer that is used to map objects in the domain model to the relational table schema while keeping them independent of each other. The main objective of the data mapper is to strip the responsibility of persistence from the entity objects in favor of classes external to the entities. The repository uses this data mapper classes to access, modify and persist these entities back to the database. A repository is a layer that mediates between the business entities and data mappers in your data access code. The business layer uses this repository for all the data access functionality it requires.
In this article series we’ll see how to create a simple data access layer in C# that uses the data mapper and repository pattern implementation. The database used in the sample is SQL Server, which can be replaced by any other relational database. I have used the enterprise library data access application block for all ADO.NET queries.
Before writing the C# code, we’ll work on the database schema. We’ll use a customer table and the CRUD procs to demonstrate the repository and data mapper sample in this article series.
The scripts for creating the customer table is
CREATE TABLE [dbo].[Customers](
      [CustomerIntId] [bigint] IDENTITY(1,1) NOT NULL,
      [FirstName] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      [LastName] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
      [Address] [varchar](500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      [CreatedDate] [datetime] NULL,
      [ChangedDate] [datetime] NULL,
      [Version] [timestamp] NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
(
      [CustomerIntId] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
Stored procedures used in the sample.
CREATE PROCEDURE [dbo].[usp_GetAllCustomers]   
AS
BEGIN
      SET NOCOUNT ON;

      SELECT [CustomerIntId] as 'CustomerIntId'
      ,[FirstName] as 'FirstName'
      ,[LastName] as 'LastName'
      ,[Address] as 'Address'
      ,[CreatedDate] as 'CreatedDate'
      ,[ChangedDate] as 'ChangedDate'
      ,[Version] as 'Version'
      FROM [dbo].[Customers]
END
CREATE PROCEDURE [dbo].[usp_GetCustomerById]
      @CustomerIntId bigint
AS
BEGIN
      SET NOCOUNT ON;

    SELECT [CustomerIntId] as 'CustomerIntId'
      ,[FirstName] as 'FirstName'
      ,[LastName] as 'LastName'
      ,[Address] as 'Address'
      ,[CreatedDate] as 'CreatedDate'
      ,[ChangedDate] as 'ChangedDate'
      ,[Version] as 'Version'
  FROM [dbo].[Customers]
  WHERE [CustomerIntId] = @CustomerIntId
END
CREATE PROCEDURE [dbo].[usp_InsertCustomer]
      @FirstName varchar(50),
      @LastName varchar(50),
      @Address varchar(500),
      @CustomerIntId bigint OUT
AS
BEGIN
      SET NOCOUNT ON;

      INSERT INTO [dbo].[Customers]
           ([FirstName]
           ,[LastName]
           ,[Address]
           ,[CreatedDate]
           ,[ChangedDate])
     VALUES
           (@FirstName
           ,@LastName
           ,@Address
           ,getdate()
           ,getdate())

      SET @CustomerIntId = SCOPE_IDENTITY()
END
CREATE PROCEDURE [dbo].[usp_UpdateCustomer]
      @CustomerIntId bigint,
      @FirstName varchar(50),
      @LastName varchar(50),
      @Address varchar(500),
      @Version timestamp,
      @VersionNew timestamp OUT
AS
BEGIN
      SET NOCOUNT ON;

    UPDATE [dbo].[Customers]
      SET [FirstName] = @FirstName
      ,[LastName] = @LastName
      ,[Address] = @Address
      ,[ChangedDate] = getdate()
      WHERE CustomerIntId = @CustomerIntId
      AND Version = @Version

      IF @@ROWCOUNT = 0
      BEGIN
            RAISERROR('Concurrent update error. Updated aborted.', 16, 2)
      END

      SELECT @VersionNew = [Version]      FROM [dbo].[Customers]
      WHERE [CustomerIntId] = @CustomerIntId   
END
CREATE PROCEDURE [dbo].[usp_DeleteCustomerById]
      @CustomerIntId bigint
AS
BEGIN
      SET NOCOUNT ON;

    DELETE FROM [dbo].[Customers]
    WHERE [CustomerIntId] = @CustomerIntId
END
Next we’ll see how to create a data access layer for accessing the Customer data that we created in the database.

NHibernate – Define Order and Product entities and mappings (Part 10)


In the previous posts on NHibernate we have seen how to configure NHibernate and create a repository pattern implementation for accessing data using NHibernate. In this post we will see how to create different levels of mappings between our entities that participate in a customer-order application. For this we need to create two more entities (Product and Order) and define mappings between them.
The classes that are used in this sample are defined as
public class Product  : BaseEntity<long>
{
    public virtual string Name { get; set; }
    public virtual decimal Amount { get; set; }
    public virtual string ModelNumber { get; set; }       
}
public class Order : BaseEntity<long>
{
    public virtual string OrderNumber { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual ISet<Product> Products { get; set; }
}
public class Customer : BaseEntity<long>
{
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string Address { get; set; }
    public virtual ISet<Order> Orders { get; set; }
}
I have defined the mapping between entities as
Customer.hbm.xml file
xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="BlogsPrajeesh.NHibernate.Domain"
                   namespace="BlogsPrajeesh.NHibernate.Domain">
  <class name="Customer" table="Customers">
    <id name="Id" column="CustomerIntId">
      <generator class="identity" />
    id>
   
   
    <version name="Version" generated="always" unsaved-value="null" type="BinaryBlob">
      <column name="Version" not-null="false" sql-type="timestamp"/>
    version>
    <property name="CreatedDate" type="DateTime" />
    <property name="ChangedDate" type="DateTime" />
    <property name="FirstName" not-null="true" />
    <property name="LastName" not-null="true" />
    <property name="Address" />
   
    <set name="Orders" inverse="true" lazy="true" cascade="delete">
      <key column="CustomerIntId"/>
      <one-to-many class="Order"/>
    set>
  class>
hibernate-mapping>
Order.hbm.xml file
xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="BlogsPrajeesh.NHibernate.Domain"
                   namespace="BlogsPrajeesh.NHibernate.Domain">
  <class name="Order" table="Orders">
    <id name="Id" column="OrderIntId">
      <generator class="identity" />
    id>
   
   
    <version name="Version" generated="always" unsaved-value="null" type="BinaryBlob">
      <column name="Version" not-null="false" sql-type="timestamp"/>
    version>
    <property name="CreatedDate" type="DateTime" />
    <property name="ChangedDate" type="DateTime" />
    <property name="OrderNumber" not-null="true" />
   
    <many-to-one name="Customer" column="CustomerIntId"/>
    <set name="Products" table="OrderProduct">
      <key column="OrderIntId"/>
      <many-to-many class="Product" column="ProductIntId"/>
    set>
  class>
hibernate-mapping>
Product.hbm.xml file
xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="BlogsPrajeesh.NHibernate.Domain"
                   namespace="BlogsPrajeesh.NHibernate.Domain">
  <class name="Product" table="Products">
    <id name="Id" column="ProductIntId">
      <generator class="identity" />
    id>
    <version name="Version" generated="always" unsaved-value="null" type="BinaryBlob">
      <column name="Version" not-null="false" sql-type="timestamp"/>
    version>
    <property name="CreatedDate" type="DateTime" />
    <property name="ChangedDate" type="DateTime" />
    <property name="Name" not-null="true" />
    <property name="Amount" />
    <property name="ModelNumber" column="Model" not-null="true" />
  class>
hibernate-mapping>
Next part of this series we’ll see how to create repositories for the Order and Product entities and use them for accessing the data.