Pages

Thursday, March 25, 2010

Getting started with Enterprise Library

As Software developers we experience common problems like Logging, Validation, Caching, Data access, Exception handling in our each and every software solutions. Implementing logging infrastructure or data access logic for every project is waste of time. Enterprise Library is set of best practices which recommended by Microsoft to be used in small to enterprise level applications.

Features come with Enterprise Library 4.1 (October 2008)

  • Caching Application block
  • Cryptography Application block
  • Data Access Application block
  • Exception Handling Application block
  • Logging Application block
  • Policy Injection Application block
  • Security Application block
  • Unity Application block
  • Validation Application block

Goals for Enterprise Library

Enterprise Library is a collection of application blocks and services intended for use by developers who build complex, enterprise-level applications. These applications are typically deployed widely and have interdependencies with other application and systems. In addition, they generally have strict security, reliability, and performance requirements.

The goals of Enterprise Library are the following:

  • Consistency. All Enterprise Library application blocks feature consistent design patterns and implementation approaches.
  • Extensibility. All application blocks include defined extensibility points that allow developers to customize the behavior of the application blocks by adding their own code.
  • Ease of use. Enterprise Library offers numerous usability improvements, including a graphical configuration tool, a simpler installation procedure, and clearer and more complete documentation and samples.
  • Integration. Enterprise Library application blocks are designed to work well together and are tested to make sure that they do. It is also possible to use the application blocks individually.

Getting started with Enterprise Library

Note: We need to install enterprise library only on Developer machines, no need to install it on deployment/production machines. Only required Enterprise library dlls should be copied to solutions bin folder or GAC.

  • Referencing Enterprise Library common files to Visual Studio project.

    Add a reference to the application block assembly (For demo purpose I am going to use Logging application block.)

    In Visual Studio, right-click your project node in Solution Explorer, and then click Add References. Click the Browse tab, and then find the location of the application block assembly and select Microsoft.Practices.EnterpriseLibrary.Logging.dll and click ok.

    Use the same procedure to set a reference to the Enterprise Library Common assembly, Microsoft.Practices.EnterpriseLibrary.Common.dll and to the ObjectBuilder assembly, Microsoft.Practices.ObjectBuilder2.dll

    Now open the source code file (e.g Program.cs) and add following namespace on top of the code.

    using Microsoft.Practices.EnterpriseLibrary.Logging;

  • Adding Configuration entry to App.Config / Web.Config

    Right click on app.config or web.config file of your project and click on Edit Enterprice Library Configuration as sown bellow,

    Now right click on config file node from node tree and select New -> Logging Application Block as shown bellow,

    Now you can see default logging config settings are displaying in the node tree.

    Also it has added a Formatted
    Event Log Trace Listener to the Event Listeners section.

  • Now we are ready to go with Enterprise Library. Following is a simple example of writing Log entry to events log using Logging application block,


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Practices.EnterpriseLibrary.Logging;


    namespace EntLibDemo
    {
    class Program
    {
    static void Main(string[] args)
    {
    LogEntry logEntry = new LogEntry();
    logEntry.EventId = 100;
    logEntry.Priority = 2;
    logEntry.Message = "Informational message";
    logEntry.Categories.Add("Trace");
    logEntry.Categories.Add("UI Events");


    Logger.Write(logEntry);
    }
    }
    }

See how easy to use Enterprise library and the Enterprise library configuration utility save us lots of time and now we can focus more on development of business features.

Download Source Code for this post.

Download PDF version of this post.

Resources

Download Enterprise Library 4.1 (Oct 2008)

Patterns & Practices – Enterprise Library latest on Codeplex

Saturday, March 20, 2010

My First NHibernate application

  1. Download NHibernate from http://www.nhforge.org
  2. Create New Visual Studio project (i name it NHibernateDemo)
  3. Add an assembly reference to NHibernate.dll

    For this example I am using NHibernate-2.1.2
    Also copy files from NHibernate-2.1.2.GA-bin\Required_For_LazyLoading\LinFu folder
    which contains supporting files for lazy loading to your Bin folder.
  4. Create database tables
    tblEmployee - Maintain employee information
    tblSkill - Maintain simple list of skills with ID and Title
    tblEmployeeSkill - Mapping table of employee and skill (many-to-many relation)

    image001
    CREATE TABLE tblEmployee(
    EmployeeID int IDENTITY(1,1) NOT NULL,
    FistName nchar(50),
    LastName nchar(50)
    DOB datetime,
    HomeAddress nchar(100)
    )
    
    
    CREATE TABLE tblSkill(
    SkillID int IDENTITY(1,1) NOT NULL,
    Title nchar(50)
    )
    
    
    CREATE TABLE  tblEmployeeSkills(
    EmployeeID int NOT NULL,
    SkillID int NOT NULL,
    AssignedDate datetime
    )   
    

  5. Create Business classes


    image003


    public class Employee
    {
    public virtual int EmployeeID { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual DateTime DateOfBirth { get; set; }
    public virtual string HomeAddress { get; set; }
    
    public virtual IList Skills { get; set; }
    }
    
    public class Skill
    {
    public virtual int SkillID { get; set; }
    public virtual string Title { get; set; }
    }      
    

    Every property of our class should be virtual.

    Because if you need lazy loading to be enabled you must mark each property as virtual. Then the nhibernate can create required proxy class for our class types. For more info about this please read this post by Davi Brion.

    Also the collection types should be IList<> or ISet. (e.g. List)
  6. Create NHibernate mappings (hbm)
    Create new XML file and name it DemoMappings.hbm.xml

    (For this example i am using a single file to contain all the classes mappings. But you can create any number of individual XML files for each mapping)

    Also remember to set Build Action property to Embedded Resource of DemoMappings.hbm.xml file.

    TIP : For visual studio intelisence for XML file please set Schema of the XML file to nhibernate-mapping.xsd . which can be found in NHibernate bin folder.


    image005
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    namespace="NHibernateDemo.BusinessObjects" assembly="NHibernateDemo">
    
    <class proxy="Skill" table="tblSkill" name="Skill">
    <id name="SkillID" column="SkillID" type="Int32">
    <generator class="identity"></generator>
    </id>
    <property name="Title" column="Title" type="string" length="50"></property>
    </class>
    
    
    <class proxy="Employee" table="tblEmployee" name="Employee" lazy="true">
    <id name="EmployeeID" column="EmployeeID" type="Int32">
    <generator class="identity"></generator>
    </id>
    
    <property name="FirstName" column="FirstName" type="String" length="50"></property>
    <property name="LastName" column="LastName" type="String" length="50"></property>
    <property name="DateOfBirth" column="DOB" type="DateTime"></property>
    <property name="HomeAddress" column="HomeAddress" type="String"></property>
    
    <bag table="tblEmployeeSkills" name="Skills" lazy="false">
    <key column="EmployeeID"></key>
    <many-to-many class="Skill" column="SkillID"></many-to-many>
    </bag>
    </class>
    </hibernate-mapping>
    
  7. Configure NHibernate

    Create hibernate.cfg.xml and set Copy to Output to Copy Always. And copy paste following,

    (If you didn’t do above then you will get error somewhat like: An exception occurred during configuration of persistence layer.)

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
    <property name="connection.provider">
    NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
    <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    <property name="connection.connection_string">
    Data Source=.\sqlexpress;Initial Catalog=DemoDB;Integrated Security=True
    </property>
    <property name="show_sql">true</property>
    </session-factory>
    </hibernate-configuration>
    

    Tip : List of supported databases and connection configuration settings
    http://community.jboss.org/wiki/DatabasessupportedbyNHibernate

  8. Creating a Employee using NHibernate

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NHibernate.Cfg;
    using NHibernateDemo.BusinessObjects;
    using NHibernate;
    
    namespace NHibernateDemo
    {
    class Program
    {
    private static ISessionFactory _sessionFactory;
    
    private static ISessionFactory SessionFactory
    {
    get
    {
    if (_sessionFactory == null)
    {
    var configuration = new Configuration();
    configuration.Configure();
    configuration.AddAssembly(typeof(Employee).Assembly);
    _sessionFactory = configuration.BuildSessionFactory();
    }
    return _sessionFactory;
    }
    }
    
    public static ISession OpenSession()
    {
    return SessionFactory.OpenSession();
    }
    
    static void Main(string[] args)
    {
    Employee employee = new Employee()
    {
    FirstName = "Dilhan",
    LastName = "Jayathilaka",
    DateOfBirth = DateTime.Now,
    HomeAddress = "Some address."
    };
    
    employee.Skills = new List();
    employee.Skills.Add(new Skill() { SkillID = 1 });
    
    using (ISession session = OpenSession())
    {
    using (ITransaction transaction =
    session.BeginTransaction())
    {
    session.Save(employee);
    transaction.Commit();
    }
    }
    }
    }
    }

    Tip: creating ISessionFactory is an expensive process and avoid creating ISessionFactory more than one instance per application. As shown above you can create static variable to keep it for entire life of the application. ISession is a light wait and you can create it for every action in your application.

Wednesday, March 3, 2010

SharePoint Discussion board reply without previous posts content.

1. Open Discussion Board -> NewForm.aspx using SharePoint Designer
2. Paste following javascript code to bottom of the "MainContentPlaceHolder"

<script language="javascript" type="text/javascript">
var d = document.getElementsByTagName("textarea");
for( var i=0; i < d.length; ++i){
if( d[i].id.indexOf('TextField') != 0 ){
d[i].value = " ";
}
}
</script>



Saturday, February 20, 2010

Query XML String as a SQL Table.

This basic sample demonstrates how to read string xml data as a normal sql table.
This is very useful is you want to parse bulk data into sql server stored procedure.
For this example I am using ArrayList of my “Test” class. And using XmlSerializer I am going to convert it in to XML. For demonstration purpose I am just declare a SQL variable “@XMLString” to hold xml data.
declare @XMLString xml

set @XMLString = '?<ArrayOfTest>
<Test>
<TestID>1</TestID >
<TestName>ASP.NET Test</TestName>
<TestDuration>2 Hrs</TestDuration>
</Test>
<Test>
<TestID>2</TestID>
<TestName>SharePoint Test</TestName>
<TestDuration>2 Hrs</TestDuration>
</Test>
<Test>
<TestID>3</TestID>
<TestName>SQL Server Test</TestName>
<TestDuration>2 Hrs</TestDuration>
</Test>
</ArrayOfTest>'

Now we can perform query against @XMLString using nodes function and xpath.


select TableAlias.ColumnAlias.value('TestID[1]','VARCHAR(20)') ,
TableAlias.ColumnAlias.value('TestName[1]','VARCHAR(20)') ,
TableAlias.ColumnAlias.value('TestDuration[1]','VARCHAR(20)')

from @XMLString.nodes('//ArrayOfTest/Test')TableAlias(ColumnAlias)


Example 2:
Here is an example of little advanced filtering with XPath.

select TableAlias.ColumnAlias.value('TestID[1]','VARCHAR(20)') ,
TableAlias.ColumnAlias.value('TestName[1]','VARCHAR(20)') ,
TableAlias.ColumnAlias.value('TestDuration[1]','VARCHAR(20)')
from @XMLString.nodes('//ArrayOfTest/Test[TestID >= 2]')TableAlias(ColumnAlias)

Download Source
Click here to Read MSDN for more info

Sunday, January 10, 2010

Discussion board anonymous reply with custom view

We can achieve this requirement by adding new list view template to Discussion List, i will call it "Flat Anonymous".

Steps,

1. Open FEATURES\DiscussionsList\schema.xml

(Exact Path : Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATURES\DiscussionsList\schema.xml)

(don't forget to Backup schema.xml file before doing any modifications)

2. Find PersonViewMinimal

3. Create a copy and name it PersonViewMinimalExtended

4. it should look like following

<Field ID="{b4ab471e-0262-462a-8b3f-c1dfc9e2d5fd}" Name="PersonViewMinimalExtended" DisplaceOnUpgrade="TRUE" Group="_Hidden" Filterable="TRUE" Sortable="TRUE" Type="Computed" DisplayName="$Resources:core,Posted_By;" ReadOnly="TRUE" AuthoringInfo="$Resources:core,picture_and_name;" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="PersonViewMinimalExtended">

<FieldRefs>
<FieldRef ID="{d31655d1-1d5b-4511-95a1-7a09e9b75bf2}" Name="Editor" />
<FieldRef ID="{adfe65ee-74bb-4771-bec5-d691d9a6a14e}" Name="PersonImage" />
<FieldRef ID="{bd2216c1-a2f3-48c0-b21c-dc297d0cc658}" Name="IsRootPost" />
</FieldRefs>

<DisplayPattern>
<Switch>
<Expr>
<Field Name="IsRootPost" />
</Expr>
<Case Value="TRUE">
<HTML><![CDATA[<table cellpadding="0" cellspacing="0"><tr><td style="padding-left: 5px;">]]></HTML>
<Field Name="PersonImage" /><HTML><![CDATA[</td></tr><tr><td style="padding-left: 5px;" nowrap>]]></HTML>
<Field Name="Editor" /><HTML><![CDATA[</td></tr></table>]]>
</HTML>
</Case>
<Default>
<HTML><![CDATA[&nbsp]]></HTML>
</Default>
</Switch>
</DisplayPattern>

</Field>





5. find $Resources:core,DiscussionViewFlat;

and create a copy from that view () .

and Change BaseViewID = "20" of newly created view

and Change display name to DisplayName="Flat Anonymous"

6. Find

from newly copied view

7. Rename it to
Now go to SharePoint site discussion board list and create new view.

Then select "Flat Anonymous" as the template.