Wednesday 7 May 2014

Generic type conversion in C#

Generic type conversion in C# is possible, but the type conversion must consider many different conversions. The following code below defines a generic method To<T> which is an extension method on object:

namespace Hemit.OpPlan.Common
{
    
    public static class ObjectExtensions
    {

        public static T To<T>(this object value)
        {
            if (value == null)
                return default(T);

            Type t = typeof(T); 

            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                Type valueType = t.GetGenericArguments()[0];
                if (value == null)
                    return default(T);
                object result = Convert.ChangeType(value, valueType);
                return (T)result;
            }
            else if (typeof(T).IsEnum)
            {
                object result = Enum.Parse(typeof(T), value.ToString());
                return (T)result;
            }
            else
            {
                try
                {
                    object result = Convert.ChangeType(value, typeof(T));
                    return (T)result;
                }
                catch (Exception err)
                {
                    Debug.WriteLine(err.Message);
                    return default(T); 
                }
            }
        }

    }
}

Next is a couple of unit tests written in NUnit for this extension method. All tests passes.

using System;
using System.Reflection;
using Hemit.OpPlan.Common.DataContract;
using NUnit.Framework;  

namespace Hemit.OpPlan.Common.Test.Extensions
{
    
    [TestFixture] 
    public class ObjectExtensionsTest
    {

        [Test]
        [TestCase("4", typeof(int), 4)]
        [TestCase("true", typeof(bool), true)]
        [TestCase(null, typeof(bool), false)]
        [TestCase(null, typeof(Nullable<bool>), null)]
        [TestCase("true", typeof(Nullable<bool>), true)]
        [TestCase("FutureOperation", typeof(OperationStatusDataContract), OperationStatusDataContract.FutureOperation)]
        [TestCase("Postponed", typeof(OperationStatusDataContract), OperationStatusDataContract.Postponed)]
        public void ToReturnsExpected(object input, Type genericTypeArgument, object expected)
        {
            MethodInfo method = typeof(ObjectExtensions).GetMethod("To");
            MethodInfo genericMethod = method.MakeGenericMethod(new Type[] { genericTypeArgument });
            object actual = genericMethod.Invoke(input, new object[]{ input });
            Assert.AreEqual(actual, expected); 
        }

        [Test] 
        public void ToReturnsExpectedWithNullableBoolean()
        {
            int? inputValue = new Nullable<int>(3);
            int actual = ((int?)inputValue).To<int>(); 
            Assert.AreEqual(actual, 3); 
        }

    }

}


The code above shows how one can call a generic method, shown in the unit test. Multiple test cases are passed into this unit test method. As is visible to the reader, the class ObjectExtensions contains the method To, which considers a conversion of an object to a designated type. The conversion itself must of course be valid, in addition one should check that the value implements IConvertible or similar interface. I have kept the code rather short and will eloborate the code if I see thare are conversions that fail, which should work.

Wednesday 23 April 2014

Using LinqKit and PredicateBuilder to create reusable predicates or filters in Entity Framework

If one has worked with Entity Framework for a while, sooner or later it becomes clear that refactoring logic into separate methods is hard, because Entity Framework must transform the code one writes in Linq to Entities into SQL. Therefore, extracting logic in EF into method calls will compile, but give a runtime error. The solution is to use the library LinqKit, created by brothers Joe and Ben Albahiri. It is available as a Nuget package: install-package LinqKit or at the following web site: LinqKit

The following simple example shows how it is possible to create a reusable predicate separated into a method of its own and call this method in Linq to entities code. Make note of the use of the AsExpandable() extension method that transforms the DbSet into an IQueryable by returning a wrapper that allows this. The code is run inside LinqPad. Make note that LinqPad has got inherent support for PredicateBuilder, but the LinqKit DLL was added as a reference. Also the namespace imports added where: System.Linq, System.Linq.Expressions and LinqKit. Press F4 to set up the additional references and imports in Linqpad.

public Expression<Func<Patient, bool>> InterestingPatient(params string[] keywords){
 var predicate = PredicateBuilder.False<Patient>(); 
 foreach (string keyword in keywords){
  string temp = keyword; 
  predicate = predicate.Or(p => p.Name.Contains(temp)); 
 }
 return predicate; 
}

void Main()
{
   Patients.AsExpandable().Where(InterestingPatient("Olsen", "Nilsen")).Dump(); 
}




The following images shows the output. Make note that Patient here is a table in the context of my project. The data shown here is test data (not real pasients of course):

Wednesday 5 March 2014

Entity Framework Code First Generic Entity store operations

This article will discuss how generic entity store operations towards a data context can be used with EF Code First. This is tested with EF 6. First, define an interface with the often used generic entity store operations:

using System;
using System.Data.Entity;

namespace TestEFCodeFirst1
{

    public interface IRepo : IDisposable
    {

        T Insert<T>(T item, bool saveNow) where T : class;

        T Update<T>(T item, bool saveNow) where T : class;

        T Delete<T>(T item, bool saveNow) where T : class;

        int Save(); 

    }

}

Then implement this interface:

using System.Data.Entity;

namespace TestEFCodeFirst1
{
    
    public class Repo<TContext> : IRepo
        where TContext : DbContext, new()
    {

        public Repo()
        {
            Context = new TContext(); 
        }

        protected TContext Context { get; private set; }

        #region IRepo Members

        public T Insert<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Added;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public T Update<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Modified;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public T Delete<T>(T item, bool saveNow) where T : class
        {
            Context.Entry(item).State = EntityState.Deleted;
            if (saveNow)
                Context.SaveChanges();
            return item; 
        }

        public void Dispose()
        {
            Context.Dispose(); 
        }

        #endregion

        #region IRepo Members


        public int Save()
        {
            return Context.SaveChanges(); 
        }

        #endregion
    }

}

Next, create a simple DbContext to test out:

  
  public class DemoDbContext : DbContext
    {


        public DemoDbContext() : base("EFCodeFirstDemoDb1")
        {
            
            
        }


        public DbSet<Student> Students { get; private set; }

    }


An example of using this db context in a derived repo class is shown next:

public class DemoRepo : Repo<DemoDbContext>
{

}

The next code shows how to use this extension method:

using System;
using System.Data.Entity;

namespace TestEFCodeFirst1
{
    class Program
    {
        static void Main(string[] args)
        {

            Database.SetInitializer(new Init()); 

            using (var repo = new DemoRepo())
            {
                repo.Insert(new Student { Name = "Hardy", DateAdded = DateTime.Now,
                LastMod = DateTime.Now}, true);

                repo.Insert(new Student
                {
                    Name = "Joey",
                    DateAdded = DateTime.Now,
                    LastMod = DateTime.Now
                }, true);                

            }
        }

    }
}


To automatically patch your database do this:

In package-manager console type: Enable-Migrations In the configuration class, set AutomaticMigrationsEnabled to true.

namespace TestEFCodeFirst1.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    internal sealed class Configuration : DbMigrationsConfiguration<TestEFCodeFirst1.DemoDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(TestEFCodeFirst1.DemoDbContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}


Add an Init class:

using TestEFCodeFirst1.Migrations;

namespace TestEFCodeFirst1
{

    internal class Init : System.Data.Entity.MigrateDatabaseToLatestVersion
    {

    }
}

This explains what is done in the line further up: Database.SetInitializer(new Init());