Showing posts with label ASP.NET. Show all posts
Showing posts with label ASP.NET. Show all posts

Tuesday, October 30, 2012

Using a Windows Service as a Timer

BACKGROUND: Recently, I came across an issue with an MVC application I was developing. This application is composed of two sections: the Frontend and Backend. The Frontend contains all the visuals (what the user sees) and requests information from the Backend. The Backend fetches all the data from the database and sent it to the Frontend.

ISSUE: The communication between the Frontend and the Backend was being lost randomly. I was never able to witness it. We only knew it happened because the Frontend would display, but no data would be present.

RESOLUTION: I am going to create a windows service that is going to run on the machine hosting the Frontend project. This service will start a timer that will tick every x minutes (5 minutes for this application). On every tick, the Frontend will send a request to the Backend. If the request does NOT return "true" from the Backend, an error will be written to the log.

STEPS: *Using Visual Studio 2010 in .NET v.4

Step 1: Create a basic Windows Service Project and Setup Project
  • http://msdn.microsoft.com/en-us/library/aa984464(v=vs.71).aspx
  • You can ignore the OnContinue() action
  • Tip - For step 7 under the section 'To create the installers for your service', I chose to use Local System instead of Local Service. Local Service was NOT working for me. I would get a permissions error when I attempted to start the service and it would not start.
Step 2: Install the service, Start the service and Verify that it is running by checking the log in the Event Viewer

Step 3: Uninstall the service

Step 4: Add the Timer to the Windows Service
  • Add private System.Timers.Timer _timer = new System.Timers.Timer() to the top of the class
  • Call SetupTimer() from the OnStart function
private void SetupTimer(){
   int interval = 300000; //default to 5 minutes
   this._timer.Interval = interval;
   this._timer.Elapsed += new System.Timers.ElapsedEventHandler(TimerElapsed);
   this._timer.Start();
}
  • Create another function called TimerElapsed() in the same file
 
void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e){
   eventLog1.WriteEntry("Communication check...");
   //Connect to a Backend function that returns true
   if (response)
     //Do nothing or write to log "success"
   else
     eventLog1.WriteEntry("Communication to Backend Failed",EventLogEntryType.Error);
     //EventLogEntryType.Error makes the entry get marked as an error in the Event Log
}

Step 5: Build the Windows Service Project

Step 6: Build the Setup Project
  • Be sure the build these projects in the proper order!
Step 7: Install the service, Start the service and Verify that it is running by checking the log in the Event Viewer


For more information, visit our site: www.rippe.com/index.htm

Friday, October 19, 2012

Enhancing Your Entity Repositories

Using a repository pattern for data access gives you clear separation and abstraction in your data layer.  The basic idea of adding repositories for data access is illustrated nicely on MSDN:



In the case of an MVC application, your controllers fit into the "Client Business Logic" area, and your Database resides in the "Data Source" area.  What's left is the repository itself, here is a typical example generated using the MVC Scaffolding project.


namespace DataModel.Models
{
    public class PartyRepository : IPartyRepository
    {
        public IQueryable<Party> All
        {
            get { return _context.Parties; }
        }
        public IQueryable<Party> AllIncluding(params Expression<Func<Party, object>>[] includeProperties)
        {
            IQueryable<Party> query = _context.Parties;
            foreach (var includeProperty in includeProperties) {
                query = query.Include(includeProperty);
            }
            return query;
        }
        public Party Find(int id){ return _context.Parties.Find(id);}
       
  //Methods removed for brevity
    }
    public interface IPartyRepository : IDisposable
    {
        IQueryable<Party> All { get; }
        IQueryable<Party> AllIncluding(params Expression<Func<Party, object>>[] includeProperties);
        Party Find(int id);
        //Methods removed for brevity
    }
}



The repository itself abstracts the dirty work of dealing with the context, and provides a great element of re-usability in your application (you can inject a repository anywhere you like and it will use the same context code).  Here are some sample use cases for some of the above methods:


_repository.Find(id); //simple lookup
_repository.All; //get everything
_repository.AllIncluding(model => model.Property1, model => model.Property2); //Get all and include some navigation properties
_repository.AllIncluding(<insert ALL navigation properties>); //Full eager fetch



Simple enough, but this structure raises some concerns:

  1. Specifying the navigation properties in your controller actions when using the repositories feels like a violation of your abstractions.  Dealing with relationships between data driven objects should stick to the data layer as much as possible.
  2. There really isn't a good method to do a full eager fetch in this scenario.  You could provide all of the include properties but that creates a maintainability issue when you add a new navigation property and have to change every location you used the including options.

Our solution to this issue was a small and simple re-working of these methods, here is an example from another object:

namespace DataModel.Models
{
    public class DocumentRepository : IDocumentRepository
    {
        private readonly Expression<Func<Document, object>>[] _allIncludes =
            {
                d => d.Department,
                d => d.Organization,
                d => d.DocumentStatus,
                d => d.DocumentType,
                d => d.FavoriteUsers
            };
        public IQueryable<Document> All(params Expression<Func<Document, object>>[] includeProperties)
        {
            IQueryable<Document> query = _context.Documents;
            foreach (var includeProperty in includeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query.Where(doc => doc.Organization.AccountId == accountId);
        }
        public IQueryable<Document> All(bool eager, params Expression<Func<Document, object>>[] includeProperties)
        {
            var includes = eager ? _allIncludes : includeProperties;
            return All(accountId, includes);
        }
        public Document Find(int id, params Expression<Func<Document, object>>[] includeProperties)
        {
            IQueryable<Document> query = _context.Documents;
            foreach (var includeProperty in includeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query.SingleOrDefault(doc => doc.Id == id);
        }
        public Document Find(int id, bool eager, params Expression<Func<Document, object>>[] includeProperties)
        {
            var includes = eager ? _allIncludes : includeProperties;
            return Find(id, includes);
        }
  //Methods removed for brevity
    }
    public interface IDocumentRepository
    {
        IQueryable<Document> All(params Expression<Func<Document, object>>[] includeProperties);
        IQueryable<Document> All(bool eager = false, params Expression<Func<Document, object>>[] includeProperties);
        Document Find(int id, params Expression<Func<Document, object>>[] includeProperties);
        Document Find(int id, bool eager = false, params Expression<Func<Document, object>>[] includeProperties);
        //Methods removed for brevity
    }
}

We simply added an eager option and an overload for the Find and the All(converting it from property to method).  Here are the new use cases:

_repository.Find(id); //simple lookup
_repository.All(); //get everything - lazy loaded
_repository.All(model => model.Property1, model => model.Property2); //Get all and include some navigation properties
_repository.All(true); or the more readable: _repository.All(eager:true); //Full eager fetch

With this modification, controlling the type of fetch you want to do is much more clear, and if we add navigation properties to the model, we only need to update the allIncludes property in the repository, not everywhere the repository is used for eager fetching.  We also still preserved the ability to lazy load, as well as specify exactly the properties you want during a fetch.

A side effect though, is we have some strange edge cases that result, for example:

_repository.All(eager:true, model => model.Property1);

In this case, the provided property is ignored and all properties are fetched.  We chose to lay the blame for this sort of issue on the developer as there are easier ways to use the methods to achieve the desired result, whatever that may be.


All code examples taken from our next version of Contract Guardian.

For more information, check out our Web Site.