The ObjectMapper .NET Project

Official blog of the AdFactum ObjectMapper .NET

Archive for June, 2006

Tutorial 3: Tracing SQL commands using Log4Net

Posted by Gerhard Stephan on 28th June 2006

For many reasons it’s quite useful to output the SQL commands into a log file. Especially for that case the ObjectMapper .NET offers the interface ISqlTracer which can be implemented by your application in order to log the sql output.

For logging purpose Log4Net is most time the first choice. Would’nt it be nice to marriage both technologies, the ObjectMapper .NET and Log4Net? That’s in fact possible and this tutorial will show how to implement it.

First thing we have to do is implementing the ISqlTracer interface. Have a look at the implementation below. I cuttet some basic stuff in order to save a little desktop space.

      /// <summary>

      /// This class traces the SQL Commands using log4net

      /// </summary>

      public class SqlTracer : ISqlTracer

      {

            private static readonly ILog log = LogManager.GetLogger(typeof (SqlTracer));

 

           

           

           

 

            /// <summary>

            /// The persister uses this method to publish the sql command

            /// </summary>

            /// <param name="original">The original string without the parameter extension.</param>

            /// <param name="extended">The extended string including the parameter content</param>

            /// <param name="affactedRows">The rows which are touched by the sql statement.</param>

            /// <param name="duration">Duration of the sql statement</param>

            public void SqlCommand(string original, string extended, int affactedRows, TimeSpan duration)

            {

                  if (extended.StartsWith("SELECT"))

                        log.Debug(extended);

                  else

                        log.Info(extended);

            }

 

            /// <summary>

            /// The persister uses this method to publish info messages, like warnings and so on.

            /// </summary>

            /// <param name="message">Message text</param>

            /// <param name="source">Source</param>

            public void ErrorMessage(string message, string source)

            {

                  log.Error(string.Concat(message, "\nSource: ", source));

            }

 

            /// <summary>

            /// Must return true, if an error logging shall be enabled.

            /// </summary>

            /// <value>

            ///   <c>true</c> if traceing of errors shall be enabled; otherwise, <c>false</c>.

            /// </value>

            public bool TraceErrorEnabled

            {

                  get { return log.IsErrorEnabled; }

            }

 

            /// <summary>

            /// Must return true, if the SQL tracing shall be enabled

            /// </summary>

            /// <value>

            ///   <c>true</c> if tracing of sql shall be enabled; otherwise, <c>false</c>.

            /// </value>

            public bool TraceSqlEnabled

            {

                  get { return log.IsInfoEnabled; }

            }

      }

 

Second thing we need is the Log4Net config file that configures the Log4Net Settings.

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

 

      <configSections>

            <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

      </configSections>

 

      <log4net>

     

            <appender name="SqlFileAppender" type="log4net.Appender.FileAppender">

                  <file value="sql_logging.txt" />

                  <appendToFile value="true" />

                  <layout type="log4net.Layout.PatternLayout">

                        <conversionPattern value="%date [%thread] %-5level: %message%newline" />

                  </layout>

            </appender>

           

            <root>

                  <level value="WARN" />

            </root>

           

            <logger name="Utils.SqlTracer">

                  <level value="DEBUG" />

                  <appender-ref ref="SqlFileAppender" />

            </logger>

 

      </log4net>

 

</configuration>

 

To complete the Log4Net framework must be initialized once when starting the application. That’s only 2 lines of code.

            string log4NetConfig = Path.GetDirectoryName("..\\..\\")+"\\logging.config";

            log4net.Config.XmlConfigurator.Configure(new FileInfo(log4NetConfig));

 

And sure: Our new SqlTracer must be initialized too when creating the Persister.

            protected AccessPersister GetAccessPersister ()

            {

                  return new AccessPersister("accessDb.mdb", new SqlTracer());

            }

That’s all. After starting the application and running the NUnit Test Cases a sql_logging.txt file must appear in your output directory (bin\debug).

You can download the example application using the following link:

Tracing SQL commands using Log4Net

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Posted in Tutorial | No Comments »

New Release – ObjectMapper .NET 1.1.528.0

Posted by Gerhard Stephan on 28th June 2006

Due to the fact that byte arrays are implementing the IList interface since .NET 2.0 I had to change the handling of BLOB types, because byte arrays should always mapped to BLOBS. In prior versions the ObjectMapper for .NET 2.0 tried to access client tables that contains byte columns … Strange thought.

Furthermore I recognized a bug when using the optimistic logging. If only the collection of an object has been changed, the update method set the LastUpdate field of the object, but did not update the database. This was pretty correct because the database row did not change. The failure relies on changing the LastUpdate field which ended up in throwing a  wrong DirtyObject Exception.

Also we removed some warnings found by the ReSharper 2.0 using Visual Studio 2005.

Cheers
Gerhard

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Posted in Releases | No Comments »

Persistent Domain Object Pattern meets the ObjectMapper .NET

Posted by Gerhard Stephan on 23rd June 2006

If you are using the ObjectMapper .NET your entities will at least need to implement the IValueObject interface. Furthermore you have to add some attributes (e.g. to specify the column length) to the properties of your business entities.

All these things are dependencies and due to this you’ll need to reference the ObjectMapper .NET assembly wherever you access the business entities.

So it would be nice if we could implement a loose coupling between the implementation details of the business entities and the UI.

The “Persistent Domain Object Pattern” – short named as PDO-Pattern – caters for that issue. It splits the business entities to an interface that is usually used by the UI and the concrete implementation for the persistent layer.

The UI only references the interfaces of the business entities. The implementation will be covered through the business components which are also using the interfaces for object exchange.

Component Diagram

For this Blog I implemented an example that shows how to separate the business entities and the user interface. Imagine you want to build an application that manages a company with one contact. Ok – not a real world example, but good enough to show how to implement the pattern.

PDO Pattern Class Diagram

As you can see the concrete implementation of the business entities implements the interfaces ICompany and IContact. Furthermore the business entities are derived from ValueObject which is important for the ObjectMapper .NET because of the object mapping.

      /// <summary>

      /// Implementation for the company

      /// </summary>

      [Table("Company")]

      public class CompanyImpl : ValueObject, ICompany

      {

            private string companyName;

            private string street;

            private string plz;

            private string city;

            private IContact companyContact;

           

           

If you are working with interfaces in a business entity you have to tell the ObjectMapper .NET the concrete implementation of the interface due to the object mapping.

            /// <summary>

            /// Gets or sets the company contact.

            /// </summary>

            /// <value>The company contact.</value>

            [Ignore]

            public IContact CompanyContact

            {

                  get { return companyContact; }

                  set { companyContact = value; }

            }

 

            /// <summary>

            /// Gets or sets the company contact used by the ObjectMapper .NET

            /// </summary>

            /// <value>The company contact.</value>

            [PropertyName("CompanyContact")]

            public ContactImpl CompanyContactImpl

            {

                  get { return companyContact as ContactImpl; }

                  set { companyContact = value; }

            }

 

As you can see the interface is tagged with an [Ignore] Attribute in order to tell the mapper that this interface should be ignored for mapping. Instead of an interface mapping we implemented a Getter / Setter to the real aggregated object. This method is not visible to the UI but used by the ObjectMapper .NET to store the Contact entity.

Last but not least the UI talks to the business components in order to receive and store the data.

      public class CompanyService 

      {

            public static ICompany CreateNewCompany ()

            { … }

                 

            public static void SaveCompany (ICompany company)

            { … }

 

            public static IList GetAllCompanies ()

            { … }

      }

 

And the UI only needs two references to external assemblies, the BusinessComponents and the Business Entities. There’s no need for adding a reference neither to the ObjectMapper nor to the concrete implementation of the Business Entities.

The complete example can be downloaded using the following link:

Persistent Domain Object Pattern meets the ObjectMapper .NET

 

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Posted in Hint | No Comments »

New Release – ObjectMapper .NET 1.1.522.0

Posted by Gerhard Stephan on 22nd June 2006

As promissed in the Release 1.0.422.0 of the ObjectMapper .NET,  I integrated a new solution for Windows CE.

This is the first draw of the ObjectMapper .NET that supports Windows CE and the integrated SQL Server Mobile Edition with a new SqlCEPersister! That allows the developer to access SDF Files using the ObjectMapper .NET.

Please keep in mind that this is the first release of the ObjectMapper .NET CE support. I think that there are still a lot bugs regarding this new feature. So please be clemently.

What else? I fixed a bug that only appeared when storing Enum properties using Microsoft .NET Framework 2.0. Furthermore I added the promised support of the TEXT data type for the SQL Server.

Because I did not want to have another release package, I combined the packages for Visual Studio 2003, 2005 and CE to one release package. That makes it more easy to switch between .NET 1.1 and .NET 2.0 or even Windows CE.

So wish you a successful time.
Gerhard

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Posted in Releases | No Comments »

Calling and Mapping Stored Procedures

Posted by Gerhard Stephan on 14th June 2006

Sometimes it is useful and necessary to call stored procedures. Imagine you have the following Stored Procedure code within your application.

                  SET ANSI_NULLS ON

                  GO

                  SET QUOTED_IDENTIFIER ON

                  GO

 

                  CREATE PROCEDURE SayHello

                        — Add the parameters for the stored procedure here

                        @Param1 as VARCHAR(255) = ‘everybody’

                  AS

                  BEGIN

                        — SET NOCOUNT ON added to prevent extra result sets from

                        — interfering with SELECT statements.

                        SET NOCOUNT ON;

 

                      — Insert statements for procedure here

                        SELECT ‘Say hello to ‘ + @Param1 as ResultValue, NEWID() as Id

                  END

                  GO

 

Due to the fact that stored procedures are specific to the SQL Server (Oracle are using PL SQL Blocks) this is handled by a special Interface. You will get that interface by casting the used persister to INativePersister. After that you can use the Execute and ExecuteWithParameter Method to call the stored procedure.

                  /*

                   * Get the low level Native Persister from the SQL Persister

                   */

                  INativePersister nativePersister = sqlPersister as INativePersister;

                 

                  // First example without Parameter

                  nativePersister.Execute("EXEC dbo.SayHello");

 

                  // Second example is using Parameters

                  nativePersister.ExecuteWithParameter("EXEC dbo.SayHello @p01", "Peter");

 

Remark: Because of the internal parameter handling it’s important that you enumerate your parameters from p01 to pNN.

Now we want to map that stored procedure to an object. Because it is necessary to have the mapping functionality this has to be done using the ObjectMapper class itself. 

                  /*

                   * Mapping the result of a stored procedures to an object

                   */

                  SortedList parameter = new SortedList();

                  parameter.Add("p01", "Peter") ;

                  IList resultSet = mapper.SelectNative(

                        typeof(Result), "EXEC dbo.SayHello @p01", parameter);

 

                  if (resultSet.Count>0)

                  {

                        Result peter = resultSet[0] as Result;

                        Console.WriteLine(peter.Value);

                  }

Remark: In order to map a stored procedure to a class it is important that the stored procedure additionaly returns a column named "Id" that contains a unique identifier for the object.

As you can see it is quite simple to map a stored procedure to a class using the ObjectMapper .NET. The working example can be downloaded using the following link:

Example: Calling and Mapping Stored Procedures

 

1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 4.00 out of 5)
Loading...

Posted in Hint | No Comments »

New Release – ObjectMapper .NET 1.0.513.0

Posted by Gerhard Stephan on 14th June 2006

The last days we recognized that it might be useful to have text fields that are longer than 4000 characters (the limit of varchar2 in oracle).

So the ObjectMapper .NET had to learn CLOBS for Oracle, and MEMO data types for Microsoft Access. Right now, the only outstanding datatype is the TEXT data type for the SQL Server. This will be implemented within the next days.

To set a string property to an unlimited length you have to add the attribute PropertyLength.

            [PropertyLength(int.MaxValue)]

            public string Content

            {

                  get { return content; }

                  set { content = value; }

            }

 

Furthermore I fixed a bug that appears when writing the difference sql file with WriteSchemaDif. Properties that have been a bigger size than the column within the current database hadn’t been reported.

And last but not least the namespace of the BackLink attribute changed to AdFactum.Data (without attributes at the end).

Cheers
Gerhard

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Posted in Releases | No Comments »

Mapping distinct classes with the same interface transparent to the application

Posted by Gerhard Stephan on 7th June 2006

Imagine that you want to map classes that implements the same interface to database.

Example:
You want to store personal informations about an individual. The individual (you) can drive a vehicle. This vehicle is implemented as an interface and has two concrete implementations like car and motorbike. So how to map these classes?

Solution 1:
You create a property in your class that returns the interface and mark this property with the attribute [GeneralLink].

             IVehicle _vehicle;

 

            /// <summary>

            /// Gets or sets the vehicle.

            /// </summary>

            /// <value>The vehicle.</value>

            [GeneralLink]

            public IVehicle Vehicle

            {

                  get { return _vehicle; }

                  set { _vehicle = value; }

            }

This is a very easy solution that handles every object that implements the interface IVehicle. To handle the different types, the ObjectMapper .NET adds an additional column that holds information about the class name of the stored object.

CREATE TABLE [INDIVIDUAL] (

         [ID] GUID, 

         [VEHICLE] GUID,

         [VEHICLE#TYP] VARCHAR(255),

         PRIMARY KEY([ID]));

The disadvantage of that method is that you can’t add foreign keys to the database column. Why? Because it contains IDs of different tables.

Solution 2:
The second way is to implement the interface property with an [Ignore] attribute and add access properties for storing the concrete object to database.

            IVehicle _vehicle;

 

            /// <summary>

            /// Gets or sets the vehicle.

            /// </summary>

            /// <value>The vehicle.</value>

            [Ignore]

            public IVehicle Vehicle

            {

                  get { return _vehicle; }

                  set { _vehicle = value; }

            }

 

            /*

             * Access Properties used by the Object Mapper .NET

             */

 

            public Car Car

            {

                  get { return _vehicle as Car; }

                  set { if (value != null) _vehicle = value; }

            }

 

            public Motorbike Motorbike

            {

                  get { return _vehicle as Motorbike; }

                  set { if (value != null) _vehicle = value; }

            }

This is a very smart solution, because the application still uses the Vehicle Property to access the vehicle for an individual. The ObjectMapper .NET uses the concrete accessor properties to set the object. Thus enables the ObjectMapper .NET to add foreign key constraints and therefore have a better object model.

CREATE TABLE [INDIVIDUAL] (

         [ID] GUID, 

         [MOTORBIKE] GUID,

         [CAR] GUID,

        

         PRIMARY KEY([ID]));

 

ALTER TABLE [INDIVIDUAL] ADD

        CONSTRAINT INDIVIDUAL_FK01

        FOREIGN KEY ([MOTORBIKE]) REFERENCES [MOTORBIKE];

       

CREATE INDEX INDIVIDUAL_FKI01 ON [INDIVIDUAL] ([MOTORBIKE]);

 

ALTER TABLE [INDIVIDUAL] ADD

        CONSTRAINT INDIVIDUAL_FK02

        FOREIGN KEY ([CAR]) REFERENCES [CAR];

       

CREATE INDEX INDIVIDUAL_FKI02 ON [INDIVIDUAL] ([CAR]);

 

Conclusion:
If you have few derivations of the interface the second solution is much smarter because it gives you the ability to add constraints to the database and enable you to query the concrete objects. If you have many different classes that implements your interface the first solution might be better, because it does not overload your class with accessor properties.

 

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Posted in Hint | No Comments »