Click here to Skip to main content
15,890,609 members
Articles / Programming Languages / C# 7.0
Tip/Trick

Work with Fluent NHibernate in Core 2.0

Rate me:
Please Sign up or sign in to vote.
4.43/5 (4 votes)
11 May 2018CPOL2 min read 22.6K   9   11   1
In this post, I will explain how we can use the ORM Fluent NHibernate in the Framework Core 2.0 for any database.

Introduction

NHibernate is an object-relational mapping (ORM) framework, it allows you to map the object oriented domain model with the tables in a relational database. To realize the mapping, we have to write XML mapping files (.hbm.xml files), and to make it easier, here comes Fluent NHibernate as an abstraction layer to do it in C# rather than XML.

Databases supported by NHibernate are:

  • SQL Server
  • SQL Server Azure
  • Oracle
  • PostgreSQL
  • MySQL
  • SQLLite
  • DB2
  • Sybase Adaptive Server
  • Firebird
  • Informix

It can support even the use of OLE DB (Object Linking and Embedding), even ODBC (Open Database Connectivity).

What makes NHibernate stronger than Entity Framework is that it integrates querying API set like LINQ, Criteria API (implementation of the pattern Query Object), integration with Lucene.NET, use of SQL even stored procedures…

NHibernate also supports:

  • Second Level cache (used among multiple ISessionFactory)
  • Multiple way of ID generation such as Identity, Sequence, HiLo, Guid, Pooled even Native mechanism used in databases
  • Flushing properties (FlushMode properties in ISession that can take these values: Auto or Commit or Never)
  • Lazy Loading
  • Generation and updating system like migration API in Entity framework (like Code First).

When Microsoft started working on the framework Core, much functionality in NHibernate wasn’t supported in .NET Core as target platform, but from the version Core 2.0, we can integrate NHibernate, even Fluent NHibernate.

Background

We should have a previous idea about NHibernate and Fluent NHibernate.

The IDE used in this sample is Visual Studio 2017.

NuGet Package

The NuGet package to use Fluent NHibernate:

PM>  Install-Package FluentNHibernate -Version 2.1.2

Create Entities

This folder will include two entities: Person and Task.

Person Entity

C#
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual DateTime CreationDate { get; set; }
public virtual DateTime UpdatedDate { get; set; }
}

Task Entity

C#
public class Task
{
public virtual string Id { get; set; }
public virtual string Title { get; set; }

public virtual string Description { get; set; }

public virtual DateTime CreationTime { get; set; }

public virtual TaskState State { get; set; }

public virtual Person AssignedTo { get; set; }

public virtual DateTime CreationDate { get; set; }
public virtual DateTime UpdatedDate { get; set; }

public Task()
{
CreationTime = DateTime.UtcNow;
State = TaskState.Open;
}

}

public enum TaskState : byte
{
/// <summary>
/// The task is Open.
/// </summary>
Open = 0,
/// <summary>
/// The task is active.
/// </summary>
Active = 1,

/// <summary>
/// The task is completed.
/// </summary>
Completed = 2,

/// <summary>
/// The task is closed.
/// </summary>
Closed = 3
}

Create Mappings

This folder will contain the mapping classes for the previous entities.

PersonMap

C#
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.Id);

Map(x => x.Name);

Map(x => x.CreationDate);
Map(x => x.UpdatedDate);
}
}

TaskMap

C#
public class TaskMap : ClassMap<Task>
{
public TaskMap()
{
Id(x => x.Id);

Map(x => x.CreationTime);
Map(x => x.State);
Map(x => x.Title);
Map(x => x.Description);
Map(x => x.UpdatedDate);
Map(x => x.CreationDate);

References(x => x.AssignedTo);
}
}

Create the SessionFactory Builder

The SessionFactories folder will include the class of SessionFactoryBuilder that will manage the schema builder and SessionFactory builder.

C#
public class SessionFactoryBuilder
 {
 
 //var listOfEntityMap = typeof(M).Assembly.GetTypes().Where
 //(t => t.GetInterfaces().Contains(typeof(M))).ToList();
 //var sessionFactory = SessionFactoryBuilder.BuildSessionFactory
 //(dbmsTypeAsString, connectionStringName, listOfEntityMap, withLog, create, update); 
 
 public static ISessionFactory BuildSessionFactory
   (string connectionStringName, bool create = false, bool update = false)
 {
 return Fluently.Configure()
 .Database(PostgreSQLConfiguration.Standard
 .ConnectionString(ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString))
 //.Mappings(m => entityMappingTypes.ForEach(e => { m.FluentMappings.Add(e); }))
 .Mappings(m =>m.FluentMappings.AddFromAssemblyOf<NHibernate.Cfg.Mappings>())
 .CurrentSessionContext("call")
 .ExposeConfiguration(cfg => BuildSchema(cfg, create, update))
 .BuildSessionFactory();
 }
 
 /// <summary>
 /// Build the schema of the database.
 /// </summary>
 /// <param name="config">Configuration.</param>
 private static void BuildSchema(Configuration config, bool create = false, bool update = false)
 {
 if (create)
 {
 new SchemaExport(config).Create(false, true);
 }
 else
 {
 new SchemaUpdate(config).Execute(false, update);
 }
 }
}

Create Services

This folder will include all different treatment that we can do like GetAll element of an Entity, add new element in database for example, in this sample, I will include two services according to our entities.

PersonService

C#
public class PersonService
{
public static void GetPerson(Person person)
{
Console.WriteLine(person.Name);
Console.WriteLine();
}
}

TaskService

C#
public class TaskService
{
public static void GetTaskInfo(Task task)
{
Console.WriteLine(task.Title);
Console.WriteLine(task.Description);
Console.WriteLine(task.State);
Console.WriteLine(task.AssignedTo.Name);
Console.WriteLine();
}
}

Add and display Table content

Now, we will try to display data from database or add a new element.

In the program, we will start by creating a session factory using the method: BuildSessionFactory implemented inside the class SessionFactoryBuilder after, we will open a new Session for every Transaction done. We start a new Transaction inside, and it depends on the operation, if we need to insert a new line in the database, we use session.SaveOrUpdate(MyObjectToAdd); after we commit this using this transaction: transaction.Commit();

C#
static void Main(string[] args)
    {
        // create our NHibernate session factory
        string connectionStringName = "add here your connection string";
        var sessionFactory =
            SessionFactoryBuilder.BuildSessionFactory(connectionStringName, true, true);
        using (var session = sessionFactory.OpenSession())
        {
            // populate the database
            using (var transaction = session.BeginTransaction()
            {
                // create a couple of Persons
                var person1 = new Person { Name = "Rayen Trabelsi" };
                var person2 = new Person { Name = "Mohamed Trabelsi" };
                var person3 = new Person { Name = "Hamida Rebai" };
                //create tasks
                var task1 = new Task
                            {Title = "Task 1", State = TaskState.Open, AssignedTo = person1};
                var task2 = new Task
                            { Title = "Task 2", State = TaskState.Closed, AssignedTo = person2 };
                var task3 = new Task
                            { Title = "Task 3", State = TaskState.Closed, AssignedTo = person3 };
                // save both stores, this saves everything else via cascading
                session.SaveOrUpdate(task1);
                session.SaveOrUpdate(task2);
                session.SaveOrUpdate(task3);
                transaction.Commit();
            }
           using (var session2 = sessionFactory.OpenSession())
            {
               //retrieve all tasks with person assigned to
                using (session2.BeginTransaction())
                {
                   var tasks = session.CreateCriteria(typeof(Task))
                        .List<Task>();
                   foreach (var task in tasks)
                   {
                       TaskService.GetTaskInfo(task);
                   }
                }
            }
           Console.ReadKey();
        }
   }
}

Conclusion

This sample is a sample use of Fluent NHibernate, in another article; I will show you another web sample using some of advantages like Criteria APIs.

History

This sample is the same that we used when we worked using EF Core 2.0 as ORM.

See this article:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Canada Canada
I am Rebaï Hamida, Microsoft MVP in Visual Studio and Development Technologies.
I'm a software architect and developer who like to build open source projects, writing articles, learning and teaching best practices. you can find out in my blog : http://hamidarebai.blogspot.com/

Innovative Software engineer : hands-on, competent software engineer, passionate and proficient C# developer, offering more than seven years of experience in the full software development lifecycle – from concept through delivery of next-generation applications and customized solutions, producing code to a consistently high standard and testing software across a variety of platforms.
Expert in advanced development methodologies, tools and processes contributing to the design and roll-out of cutting-edge software applications.
Known for excellent troubleshooting skills – able to analyze code and engineer well-researched, cost-effective and responsive solutions.


Success is only a consequence of a continuous work and remarkable intelligence.
I believe that I have to make a change in my country, I can’t live without leaving my footprint.

Comments and Discussions

 
QuestionFor Vote Pin
didourebai14-May-18 5:13
professionaldidourebai14-May-18 5:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.