Arif Khan

August 21, 2014

Introduce Audit logging to your EF application using the Repository & Unit of Work patterns

Filed under: .Net — Tags: , , — arif @ 11:35 am

Recently, I began exploring how to add audit logging to an existing application that was built using Entity Framework. I wanted a generic implementation that was applicable to any db entity & also allowed flexibility in the amount of information logged.

The following Proof of Concept project, found here, is an interactive Console Application that features the following:

  1. Using Unit of Work & Repository patterns to accomplish Audit logging.
  2. Using the Interception pattern with Unity IoC
  3. Using the MVC pattern in a Console application

The poco entities are persisted in an instance of SQL Server Express LocalDB, that comes installed with Visual Studio (2012 & 2013) by default.

The Entity Framework DbContext facilitates tracking uncommitted changes. Using what DbContext already offers, and by introducing the Unit of Work pattern, I was able to inspect what has changed and log it prior to committing the changes to the database. What’s essential is that the DbContext is shared between the repository class and the Unit of Work (UoW) class and that the Save method only exists on the UoW class. Also, by utilizing dependency injection, you can configure your Repository & UoW classes correctly just once.

And finally, I created a custom attribute called AuditableAttribute that takes an enum, AuditScope, as a constructor argument. AuditScope defines the following members: ClassOnly, PropertiesOnly, ClassAndProperties. The poco classes that must support auditing should be decorated with the custom attribute and the level of logging desired should be specified using the AuditScope enum. ClassOnly means only Addition & Deletion of a record, PropertiesOnly means also tracking properties that have changed and ClassAndProperties implies both.

And here is the Save method of the UoW class. As you can see it inspects if the class supports Auditable and the level of logging desired. It creates a json record in the AuditRepository.

Snippet

public void Save()
        {
            foreach (DbEntityEntry dbEntry in _context.ChangeTracker.Entries().Where(
                x => x.State == EntityState.Added || x.State == EntityState.Deleted || x.State == EntityState.Modified))
            {
                Type employeeType = dbEntry.State == EntityState.Deleted 
                    ? dbEntry.OriginalValues.ToObject().GetType() 
                    : dbEntry.CurrentValues.ToObject().GetType();
                AuditableAttribute auditableAttr = employeeType.GetCustomAttribute<AuditableAttribute>();
 
                if (auditableAttr == null)
                {
                    continue;
                }
 
                if (auditableAttr.AuditScope == AuditScope.ClassOnly || auditableAttr.AuditScope == AuditScope.ClassAndProperties)
                {
                    if (dbEntry.State == EntityState.Added || dbEntry.State == EntityState.Deleted)
                    {
                        var describable = dbEntry.Entity as IDescribable;
                        if (describable != null)
                        {
                            dynamic auditLog = new JObject();
                            auditLog.state = dbEntry.State.ToString();
                            auditLog.data = describable.Describe();
 
                            var auditEntry = new Audit
                            {
                                EntityName = dbEntry.Entity.GetType().Name,
                                LogData = auditLog.ToString()
                            };
 
                            this.AuditRepository.Add(auditEntry);
                        }
                    }
                }
                if (auditableAttr.AuditScope == AuditScope.PropertiesOnly || auditableAttr.AuditScope == AuditScope.ClassAndProperties)
                {
                    if (dbEntry.State == EntityState.Modified)
                    {
                        foreach (string propertyName in dbEntry.OriginalValues.PropertyNames)
                        {
                            // For updates, we only want to capture the columns that actually changed
                            var origValue = dbEntry.OriginalValues.GetValue<object>(propertyName);
                            var newValue = dbEntry.CurrentValues.GetValue<object>(propertyName);
                            if (!object.Equals(origValue, newValue))
                            {
                                dynamic auditLog = new JObject();
                                auditLog.propertyName = propertyName;
                                auditLog.origValue = origValue;
                                auditLog.newValue = newValue;
 
                                var auditEntry = new Audit
                                {
                                    EntityName = dbEntry.Entity.GetType().Name,
                                    LogData = auditLog.ToString()
                                };
 
                                this.AuditRepository.Add(auditEntry);
                            }
                        }
                    }
                }
            }
 
            // In all versions of Entity Framework, whenever you execute SaveChanges() to insert, 
            // update or delete on the database the framework will wrap that operation in a transaction. 
            // This transaction lasts only long enough to execute the operation and then completes. 
            // When you execute another such operation a new transaction is started.
 
            _context.SaveChanges();
        }

Although, the interactive menu’s will guide you through the list of available commands in the current menu screen, the following commands can be typed within any screen.

EXIT -> exits the system
AUDIT -> activates the Audit menu
HOME -> activates the Home menu

There is a lot of other things going on in this application. Such as using the Unity Interceptor behavior to intercept the Activate method on the controller classes & display the View, which is essentially a text file that contains the commands for that controller. You can follow the onscreen menu options when running the app.

The source code can be found here.

December 27, 2012

Extending the app with a Service Stack repository

Filed under: .Net, Service Stack — Tags: , — arif @ 3:50 pm

In continuing to extend this app, I created a new repository type. Because I already had the IDataRepository abstraction in place, I thought it would be interesting to create a ServiceStackRepository from it.

Service Stack is an open-source web services framework that allows you to do messaging similar to WCF. I was happy that like WCF, it also allows for self-hosting. This is really a no-brainer since messaging technologies that allow cross process communication shouldn’t count on a web server as the only end point.

First, the changes I had to make. I try to follow the open-closed principle in writing my code. There is not much change in the existing projects, other than some refactoring, such as creating a new project, GettingReady.Core, and moving the 2 repositories (InMemoryRepository, ServiceStackRepository) to it. Other than that, there should be minimal changes to the existing code. The new additions include:

  • New console application, GettingReady.ServStack.Service. Hosts the service stack web service API.
  • New repository type, ServiceStackRepository, to communicate with the service. This makes use of the C# client libraries that come with Service Stack.
  • Additional collection element in app.config to specify the different repository types and the default one to use. See below.


<repositories default=ServiceStackRepository>

   <repository name=InMemoryRepository type=GettingReady.Core.InMemoryRepository, GettingReady.Core />            

   <repository name=ServiceStackRepository type=GettingReady.Core.ServiceStackRepository, GettingReady.Core />

</repositories>

The Service Stack framework also comes with its own IoC container (Funq) and its own ORM (OrmLite). Both are pretty simple to use and worked out well in this example. SS also makes it easy to create RESTful services. However, unlike WCF, which allows you to define routes based on procedures, SS allows you to define routes based on the DTO itself. This somewhat threw me off for a bit because I was trying to have the parameters passed via the route auto fill the service method parameters. This works well in WCF. However, with SS, additional params passed via the route are expected as properties on the DTO itself. Because I didn’t want to alter the shared model classes I was using as the DTO, I ended up inheriting it and then adding to it the property I was passing in the route. Interestingly, passing a base type where a derived type was expected, did not break the service contract, which I believe it would in WCF. Another positive was that the route was a combination of the url and the HTTP verb. So I could add a GET and a POST to the same url and pass different DTO to each action. You can build very clean API’s with that.

Routes

                .Add<CommandEntry>("/command/{Id}"ApplyTo.Post)

                .Add<CommandQuery>("/command/{Id}"ApplyTo.Get);

The entire source code can still be found here. The modified App.config is here.

July 4, 2012

Extending the app with an F# command

Filed under: .Net — Tags: — arif @ 9:27 am

I posted a C# solution here that used DI to load instances of the ICommand abstraction that were specified in the program’s config file. I thought it would be interesting, and a learning experience, to build a command using F# that would coexist with the other commands. I also wanted to make it a little more interesting than a simple “Hello World”.

The example below uses F# to make a call to the Netflix REST API and returns a list of movies with the term “Pirates” in it. The first thing to do is to register for a Netflix developer account and off you go. I implement the ICommand interface at the bottom of the code file because apparently F# type inference works in a sequential manner and I needed to call some private members from there.

namespace Commands.Netflix 

open System

open System.Net

open System.Xml.Linq

open GettingReady.Model 

type ReturnMovie() =  

 member private this.GetMoviesWithTermPirates =

  let searchTerm = “pirates”

  let requestUri = new Uri(String.Format(http://api-public.netflix.com/catalog/titles/autocomplete?oauth_consumer_key={0}&term={1}”

   , Globals.consumerKey, searchTerm))

  let request = WebRequest.Create(requestUri) :?> HttpWebRequest

  request.Method <- “GET”

  let response = request.GetResponse() :?> HttpWebResponse

  let moviesElement = XElement.Load(response.GetResponseStream())

  response.Close() 

  let inline implicit arg =

   ( ^a : (static member op_Implicit : ^b -> ^a) arg)

  let (!!) : string -> XName = implicit

  let autoComplete = !!“autocomplete_item”

  let title = !!“title”

  let short = !!“short”

  let titleNames =

   moviesElement.Elements(autoComplete)

   |> Seq.map (fun x-> x.Element(title).Attribute(short).Value)

  let listMovieTitles = List.ofSeq titleNames

  listMovieTitles

 member private this.GetRandomMovie =

  let movieList = this.GetMoviesWithTermPirates

  let rand = new Random()

  let next = rand.Next(0, movieList.Length – 1)

  List.nth movieList next

 interface ICommand with

  member x.Print mode =

   String.Format(“Returning movie {0}”, x.GetRandomMovie)

  member x.CanPrint mode = true

Making the app aware of this new command was even simpler. Just added the entry below to the config file:

            <command key="9" name="ReturnMovie" type="Commands.Netflix.ReturnMovie, Commands.Netflix">
                <previousCommands>
                    <add name="LeaveHome" />
                </previousCommands>
            </command>

June 18, 2012

Using the Unity IoC container

Filed under: .Net — Tags: , , — arif @ 10:31 pm

I took a stab at solving this problem using Dependency Injection. The entire source code is available here. I wanted to create an extensible application. So, I broke it up into 3 projects:

  1. The Console App
  2. GettingReady.Model (contains the abstractions/API)
  3. GettingReady.Commands (the commands that implement the abstractions)

I needed a way to loosely connect the different commands and mandate a proper sequence of calling them or else fail. I decided to make use of the Console application’s config file, though it could as well have been a separate xml file or any other storage.

This is what my App.config looks like. The entire file is can be viewed here.

    <GettingReady>
        <commands>
            <command key="1" name="Footwear" type="GettingReady.Commands.Footwear, GettingReady.Commands">
                <previousCommands>
                    <add name="RemovePJs" />
                    <add name="Socks"  />
                    <add name="Pants" />
                </previousCommands>
            </command>
            <command key="2" name="Headwear" type="GettingReady.Commands.Headwear, GettingReady.Commands">
                <previousCommands>
                    <add name="RemovePJs" />
                    <add name="Shirt" />
                </previousCommands>
            </command>

One of the first things I needed to do upon startup was the read the config file and register all the different types with the IoC container. That is done with the code below that is called from the main entry point.

<<Program.cs>> 
        static ICommandProcessor RegisterDependencies() 
        { 
            Container.RegisterType<ICommandProcessorCommandProcessor>(new ContainerControlledLifetimeManager(), 
                                                                        new InjectionConstructor( 
                                                                            new object[] 
                                                                                { 
                                                                                    new ResolvedParameter<IDataRepository>(), 
                                                                                    Container 
                                                                                } 
                                                                            )); 
            Container.RegisterType<IDataRepositoryInMemoryRepository>(); 
            var commandProcessor = Container.Resolve<ICommandProcessor>(); 
            var commandsConfigurationSection = ConfigurationManager.GetSection("GettingReady"as GettingReadyConfigurationSection; 
            var commands = commandsConfigurationSection.Commands; 
            foreach (CommandElement commandElement in commands) 
            { 
                var key = commandElement.Key; 
                var name = commandElement.Name; 
                var typeName = commandElement.TypeFullName; 
                commandProcessor.RegisterDependency(key, name, typeName, commandElement.PreviousCommands.GetNames()); 
            } 
            return commandProcessor; 
        } 
<<CommandProcessor.cs>> 
        public void RegisterDependency(int keyCode, string commandName, string commandTypeName, IEnumerable<string> previousCommandNames) 
        { 
            _repository.RegisterCommand(new CommandInfo
                                       { 
                                           KeyCode = keyCode, 
                                           Name = commandName, 
                                           TypeName = commandTypeName, 
                                           PreviousCommandNames = previousCommandNames 
                                       }); 
            _container.RegisterType(typeof(ICommand), Type.GetType(commandTypeName), commandName, 
                new TransientLifetimeManager(), 
                new InjectionMember[] { }); 
        } 

The method CommandProcessor.RegisterDepedency does 2 things. It registers the command with the DI container as well with a repository that stores the command info and is used to retrieve the command by its key code. The repository is also an abstraction (IDataRepository) and is constructor injected into the CommandProcessor. For this simple case, I only provide an InMemoryRepository.

One of the things I strive to do is keep the abstractions small and avoid bloat. The ICommand interface only contains 2 methods:

    public interface ICommand
    { 
        String Print(Mode mode); 
        bool CanPrint(Mode mode); 
    } 

For this reason, I had to introduce the CommandProcessor to handle all the work of which command is allowed to run and when.

Loose coupling is practiced and the concrete types in the Commands project are not referenced. Instead we program to abstractions found in the Model project. Using DI, I was able to solve this in a clean manner.

Coding problem: Getting dressed

Filed under: Uncategorized — arif @ 9:41 pm

Below is an interesting coding problem that I will be referencing to in subsequent posts.

 

Problem: You must get fully dressed before leaving the house

Rules:
At the start, assume you have PJ’s on
Only 1 piece of each item of clothing may be put on
You cannot put on socks when it is hot
You cannot put on jacket when it is hot
Socks must be put on before footwear
Shirt must be put on before headwear and jacket
Pants must be put on before footwear
Pajamas must be taken off before anything can be put on
You cannot leave the house until all items of clothing are on (except socks and a jacket when it’s hot)
If an invalid command is issued, please respond with “fail”

Input: Temperature type (HOT|COLD) and a comma separated list of numeric commands
Command            |    Description    |    Hot Response    |    Cold Response
—————————————————————————————-
1        |    Put on footwear    |    “sandals”    |    “boots”
2         |    Put on headwear    |    “sunglasses”    |    “hat”
3        |    Put on socks    |    fail        |    “socks”
4        |    Put on shirt    |    “shirt”        |    “shirt”
5        |    Put on jacket    |    fail        |    “jacket”
6        |    Put on pants    |    “shorts”    |    “pants”
7        |    Leave house    |    “leaving house”    |    “leaving house”
8        |    Take off pajamas|    “Removing PJs”    |    “Removing PJs”

Here are some example scenarios

Successful
———-
Input: HOT 8, 6, 4, 2, 1, 7
Output: Removing PJs, shorts, shirt, sunglasses, sandals, leaving house

Input: COLD 8, 6, 3, 4, 2, 5, 1, 7
Output: Removing PJs, pants, socks, shirt, hat, jacket, boots, leaving house

Failure
——-
Input: HOT 7
Output: failure

Input: HOT 8, 6, 6
Output: Removing PJs, shorts, fail

Input: HOT 8, 6, 3
Output: Removing PJs, shorts, fail

Input: COLD 8, 6, 3, 4, 2, 5, 7
Output: Removing PJs, pants, socks, shirt, hat, jacket, fail

Input: COLD 8, 6, 3, 4, 2, 5, 1
Output: Removing PJs, pants, socks, shirt, hat, jacket, boots, fail

Input: COLD 6
Output: fail

 

The Silver is the New Black Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 53 other followers