diff --git a/GmaWebService/Code/Database.cs b/GmaWebService/Code/Database.cs
new file mode 100644
index 0000000..8fe3eb2
--- /dev/null
+++ b/GmaWebService/Code/Database.cs
@@ -0,0 +1,81 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Data.SQLite;
+using GmaWebService.Code.Helper;
+
+namespace GmaWebService.Code
+{
+    public abstract class Database
+    {
+        protected delegate T FillObject<T>(SQLiteDataReader reader);
+
+        protected string DatabasePath
+        {
+            get;
+            set;
+        }
+
+        protected Database(string databasePath)
+        {
+            DatabasePath = databasePath;
+        }
+
+        protected T ReadRow<T>(string queryString, FillObject<T> builder, T defaultValue)
+        {
+            using(Query query = new Query(DatabasePath, queryString)) {
+                if(query.Reader.Read()) {
+                    return builder(query.Reader);
+                } else {
+                    return defaultValue;
+                }
+            }
+        }
+
+        protected T ReadRow<T>(string queryString, FillObject<T> builder)
+        {
+            return ReadRow<T>(queryString, builder, default(T));
+        }
+
+        protected int ReadInt(string queryString) {
+            return ReadRow(queryString, delegate(SQLiteDataReader reader)
+            {
+                return DatabaseHelperMethods.SafeInt32(reader, 0);
+            }, 0);
+        }
+
+        protected List<T> ReadList<T>(string queryString, FillObject<T> builder, int? start, int? end)
+        {
+            List<T> ret = new List<T>();
+
+            using (Query query = new Query(DatabasePath, queryString))
+            {
+                int counter = 0;
+                while (query.Reader.Read())
+                {
+                    // select from start to end
+                    if (start.HasValue && counter < start)
+                    {
+                        counter++;
+                        continue;
+                    }
+                    if (end.HasValue && counter > end) break;
+                    counter++;
+
+                    // add the item to the list
+                    T item = builder(query.Reader);
+                    if (item != null)
+                        ret.Add(item);
+                }
+            }
+
+            return ret;
+        }
+
+        protected List<T> ReadList<T>(string queryString, FillObject<T> builder)
+        {
+            return ReadList<T>(queryString, builder, null, null);
+        }
+    }
+}
diff --git a/GmaWebService/Code/MPTvSeries.cs b/GmaWebService/Code/MPTvSeries.cs
index 7f38f26..1f1d93f 100644
--- a/GmaWebService/Code/MPTvSeries.cs
+++ b/GmaWebService/Code/MPTvSeries.cs
@@ -8,139 +8,74 @@ using GmaWebService.Interfaces;
 
 namespace GmaWebService.Code
 {
-    public class MPTvSeries
+    public class MPTvSeries : Database
     {
-        public MPTvSeries()
+        private Database database;
+
+        public MPTvSeries() : base(Utils.GetMPDbLocations().TvSeries)
         {
-  
         }
 
-        #region TvSeries
-
+        #region Series
         public int GetSeriesCount()
         {
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
-            {
-                return 0;
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select COUNT(series.ID) " +
-                              "from online_series as series ";
-
-            SQLiteDataReader reader = cmd.ExecuteReader();
-
-            if (reader.Read())
-            {
-                int nums = DatabaseHelperMethods.SafeInt32(reader, 0);
-                return nums;
-            }
-            return 0;
+            return ReadInt("SELECT COUNT(online_series.ID) FROM online_series");
         }
 
         public List<WebSeries> GetAllSeries()
         {
-            return GetSeries(0, -99);
+            return GetSeriesImplementation(null, null);
         }
 
         public List<WebSeries> GetSeries(int _start, int _end)
         {
-            List<WebSeries> allSeries = new List<WebSeries>();
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
-            {
-                return allSeries;
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select series.ID, series.Pretty_Name, series.EpisodeCount, series.IMDB_ID, series.Rating, series.RatingCount, " +
-                              "series.fanart, series.PosterBannerFileName, series.CurrentBannerFileName, series.Genre " +
-                              "from online_series as series";
-
-            int counter = 0;
-            SQLiteDataReader reader = cmd.ExecuteReader();
-            while (reader.Read())
+            return GetSeriesImplementation(_start, _end);
+        }
+
+        private List<WebSeries> GetSeriesImplementation(int? start, int?end) {
+            string sql = "Select series.ID, series.Pretty_Name, series.EpisodeCount, series.IMDB_ID, series.Rating, series.RatingCount, " +
+                         "series.fanart, series.PosterBannerFileName, series.CurrentBannerFileName, series.Genre " +
+                         "from online_series as series";
+            return ReadList<WebSeries>(sql, delegate(SQLiteDataReader reader)
             {
-                if (counter >= _start)
-                {
-                    if (_end != -99 && counter > _end) break;
-                    WebSeries series = new WebSeries();
-                    series.Id = DatabaseHelperMethods.SafeInt32(reader, 0);
-                    if (series.Id != 0)
-                    {
-                        series.PrettyName = DatabaseHelperMethods.SafeStr(reader, 1);
-                        series.EpisodeCount = DatabaseHelperMethods.SafeInt32(reader, 2);
-                        series.ImdbId = DatabaseHelperMethods.SafeStr(reader, 3);
-                        series.Rating = DatabaseHelperMethods.SafeFloat(reader, 4);
-                        series.RatingCount = DatabaseHelperMethods.SafeInt32(reader, 5);
+                WebSeries series = new WebSeries();
+                series.Id = DatabaseHelperMethods.SafeInt32(reader, 0);
+                if (series.Id == 0) return null;
+
+                series.PrettyName = DatabaseHelperMethods.SafeStr(reader, 1);
+                series.EpisodeCount = DatabaseHelperMethods.SafeInt32(reader, 2);
+                series.ImdbId = DatabaseHelperMethods.SafeStr(reader, 3);
+                series.Rating = DatabaseHelperMethods.SafeFloat(reader, 4);
+                series.RatingCount = DatabaseHelperMethods.SafeInt32(reader, 5);
 
-                        String fanartUrl = DatabaseHelperMethods.SafeStr(reader, 6);
-                        series.CurrentFanartUrl = CreateFanartUrl(fanartUrl);
+                String fanartUrl = DatabaseHelperMethods.SafeStr(reader, 6);
+                series.CurrentFanartUrl = CreateFanartUrl(fanartUrl);
 
-                        String posterUrl = DatabaseHelperMethods.SafeStr(reader, 7);
-                        series.CurrentPosterUrl = CreateBannerUrl(posterUrl);
+                String posterUrl = DatabaseHelperMethods.SafeStr(reader, 7);
+                series.CurrentPosterUrl = CreateBannerUrl(posterUrl);
 
-                        String bannerUrl = DatabaseHelperMethods.SafeStr(reader, 8);
-                        series.CurrentBannerUrl = CreateBannerUrl(bannerUrl);
-                        series.GenreString = DatabaseHelperMethods.SafeStr(reader, 9);
-                        series.Genres = Utils.SplitString(series.GenreString);
+                String bannerUrl = DatabaseHelperMethods.SafeStr(reader, 8);
+                series.CurrentBannerUrl = CreateBannerUrl(bannerUrl);
+                series.GenreString = DatabaseHelperMethods.SafeStr(reader, 9);
+                series.Genres = Utils.SplitString(series.GenreString);
 
-                        allSeries.Add(series);
-                    }
-                    
-                }
-                counter++;
-                //movies.Add(new WebVideo(reader.GetInt32(0), SafeStr(reader, 1), SafeStr(reader, 2), SafeStr(reader, 3), SafeStr(reader, 4)));
-            }
-            reader.Close(); reader.Dispose(); cmd.Dispose(); db.Close(); db.Dispose();
-            return allSeries;
+                return series;
+            }, start, end);
         }
 
-
         public WebSeriesFull GetFullSeries(int _seriesId)
         {
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
+            string sql =
+                  "Select series.ID, series.Pretty_Name, series.EpisodeCount, series.IMDB_ID, series.Rating, series.RatingCount, " +
+                  "series.fanart, series.PosterBannerFileName, series.CurrentBannerFileName, series.Genre, " +
+                  "series.origName, series.Status, series.SortName, series.BannerFileNames, series.Actors,series.PosterFileNames, " +
+                  "series.ContentRating, series.Network, series.Summary, series.AirsDay, series.AirsTime, " +
+                  "series.EpisodesUnWatched, series.Runtime, series.FirstAired, series.choosenOrder " +
+                  "from online_series as series " +
+                  "where series.ID=" + _seriesId;
+            return ReadRow<WebSeriesFull>(sql, delegate(SQLiteDataReader reader)
             {
-                return null;
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select series.ID, series.Pretty_Name, series.EpisodeCount, series.IMDB_ID, series.Rating, series.RatingCount, " +
-                              "series.fanart, series.PosterBannerFileName, series.CurrentBannerFileName, series.Genre, " +
-                              "series.origName, series.Status, series.SortName, series.BannerFileNames, series.Actors,series.PosterFileNames, " +
-                              "series.ContentRating, series.Network, series.Summary, series.AirsDay, series.AirsTime, " +
-                              "series.EpisodesUnWatched, series.Runtime, series.FirstAired, series.choosenOrder " +
-                              "from online_series as series " +
-                              "where series.ID=" + _seriesId;
-
-            SQLiteDataReader reader = cmd.ExecuteReader();
-            WebSeriesFull series = null;
-            if (reader.Read())
-            {
-                series = new WebSeriesFull();
+                WebSeriesFull series = new WebSeriesFull();
                 series.Id = DatabaseHelperMethods.SafeInt32(reader, 0);
                 series.PrettyName = DatabaseHelperMethods.SafeStr(reader, 1);
                 series.EpisodeCount = DatabaseHelperMethods.SafeInt32(reader, 2);
@@ -164,15 +99,17 @@ namespace GmaWebService.Code
                 series.SortName = DatabaseHelperMethods.SafeStr(reader, 12);
 
                 String[] altBannerUrls = Utils.SplitString(DatabaseHelperMethods.SafeStr(reader, 13));
-                for (int i = 0; i < altBannerUrls.Length; i++) {
+                for (int i = 0; i < altBannerUrls.Length; i++)
+                {
                     altBannerUrls[i] = CreateBannerUrl(altBannerUrls[i]);
                 }
                 series.BannerUrls = altBannerUrls;
-               
+
                 series.Actors = Utils.SplitString(DatabaseHelperMethods.SafeStr(reader, 14));
-                
+
                 String[] altPosterUrls = Utils.SplitString(DatabaseHelperMethods.SafeStr(reader, 15));
-                for(int i = 0; i < altPosterUrls.Length; i++){
+                for (int i = 0; i < altPosterUrls.Length; i++)
+                {
                     altPosterUrls[i] = CreateBannerUrl(altPosterUrls[i]);
                 }
                 series.PosterUrls = altPosterUrls;
@@ -186,56 +123,32 @@ namespace GmaWebService.Code
                 series.Runtime = DatabaseHelperMethods.SafeInt32(reader, 22);
                 series.FirstAired = DatabaseHelperMethods.SafeDateTime(reader, 23);
                 series.EpisodeOrder = DatabaseHelperMethods.SafeStr(reader, 24);
-            }
-            reader.Close(); reader.Dispose(); cmd.Dispose(); db.Close(); db.Dispose();
-            return series;
+
+                return series;
+            });
         }
+        #endregion
 
-        #region seasons
+        #region Seasons
         public List<WebSeason> GetAllSeasons(int _seriesId)
         {
-            return GetSeasonsByNumber(_seriesId, -99);//all seasons;
+            return GetSeasonsByNumber(_seriesId, null);
         }
 
         public WebSeason GetSeason(int _seriesId, int _seasonNumber)
         {
-            List<WebSeason> season = GetSeasonsByNumber(_seriesId, _seasonNumber);
-            if (season != null && season.Count == 1)
-            {
-                return season[0];
-            }
-            else
-            {
-                return null;
-            }
+            return GetSeasonsByNumber(_seriesId, _seasonNumber).FirstOrDefault();
         }
 
-        private List<WebSeason> GetSeasonsByNumber(int _seriesId, int _seasonNumber)
+        private List<WebSeason> GetSeasonsByNumber(int _seriesId, int? _seasonNumber)
         {
-            List<WebSeason> seasons = new List<WebSeason>();
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
-            {
-                return seasons;
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select season.ID, season.SeriesID, season.SeasonIndex, season.CurrentBannerFileName, season.BannerFileNames, " +
-                              "season.EpisodeCount, season.EpisodesUnWatched " +
-                              "from season as season " +
-                              "where season.SeriesID=" + _seriesId +
-                              (_seasonNumber != -99 ? (" and season.SeasonIndex=" + _seasonNumber) : "");
+            string sql = "Select season.ID, season.SeriesID, season.SeasonIndex, season.CurrentBannerFileName, season.BannerFileNames, " +
+                         "season.EpisodeCount, season.EpisodesUnWatched " +
+                         "from season as season " +
+                         "where season.SeriesID=" + _seriesId +
+                         (_seasonNumber != null ? (" and season.SeasonIndex=" + _seasonNumber.Value) : "");
 
-            SQLiteDataReader reader = cmd.ExecuteReader();
-
-            while (reader.Read())
+            return ReadList<WebSeason>(sql, delegate(SQLiteDataReader reader)
             {
                 WebSeason season = new WebSeason();
                 season.Id = DatabaseHelperMethods.SafeStr(reader, 0);
@@ -251,213 +164,128 @@ namespace GmaWebService.Code
                 season.AlternateSeasonBanners = alternateBanners;
                 season.EpisodesCount = DatabaseHelperMethods.SafeInt32(reader, 5);
                 season.EpisodesCountUnwatched = DatabaseHelperMethods.SafeInt32(reader, 6);
-                seasons.Add(season);
-            }
-            return seasons;
+                return season;
+            });
         }
         #endregion
 
-        #region episodes
+        #region Episodes
         public List<WebEpisode> GetAllEpisodes(int _seriesId)
         {
-            return GetEpisodesForSeasonAndRange(_seriesId, -99, 0, -99);
+            return GetEpisodesForSeasonAndRange(_seriesId, null, null, null);
         }
 
         public List<WebEpisode> GetEpisodes(int _seriesId, int _start, int _end)
         {
-            return GetEpisodesForSeasonAndRange(_seriesId, -99, _start, _end);
+            return GetEpisodesForSeasonAndRange(_seriesId, null, _start, _end);
         }
 
-
         public List<WebEpisode> GetEpisodesForSeason(int _seriesId, int _seasonId, int _start, int _end)
         {
             return GetEpisodesForSeasonAndRange(_seriesId, _seasonId, _start, _end);
-
         }
 
         public List<WebEpisode> GetAllEpisodesForSeason(int _seriesId, int _seasonNumber)
         {
-            return GetEpisodesForSeasonAndRange(_seriesId, _seasonNumber, 0, -99);
-
-        }
-
-        public int GetEpisodesCount(int _seriesId)
-        {
-            return GetEpisodesCountForSeason(_seriesId, -99);
-        }
-
-        public int GetEpisodesCountForSeason(int _seriesId, int _season)
-        {
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
-            {
-                return 0;
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select COUNT(episodes.EpisodeId) " +
-                              "from online_episodes as episodes " +
-                              "where episodes.SeriesID=" + _seriesId +
-                              (_season != -99 ? (" and SeasonIndex=" + _season) : "");//limit to season if season != -99 (all)
-
-
-            SQLiteDataReader reader = cmd.ExecuteReader();
-
-            if (reader.Read())
-            {
-                int nums = DatabaseHelperMethods.SafeInt32(reader, 0);
-                return nums;
-            }
-            return 0;
+            return GetEpisodesForSeasonAndRange(_seriesId, _seasonNumber, null, null);
         }
 
-        private List<WebEpisode> GetEpisodesForSeasonAndRange(int _seriesId, int _season, int _start, int _end)
+        private List<WebEpisode> GetEpisodesForSeasonAndRange(int _seriesId, int? _season, int? _start, int? _end)
         {
-            Dictionary<String, WebEpisode> allEpisodes = new Dictionary<String, WebEpisode>();
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
-            {
-                return new List<WebEpisode>();
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select online_eps.CompositeID, online_eps.EpisodeId, online_eps.EpisodeName, online_eps.SeasonIndex, online_eps.EpisodeIndex, online_eps.Watched, online_eps.FirstAired, " +
+            List<String> alreadyDone = new List<String>();
+            string sql      = "Select online_eps.CompositeID, online_eps.EpisodeId, online_eps.EpisodeName, online_eps.SeasonIndex, online_eps.EpisodeIndex, online_eps.Watched, online_eps.FirstAired, " +
                               "online_eps.thumbFilename, online_eps.Rating, online_eps.RatingCount, " +
                               "local_eps.IsAvailable, local_eps.videoWidth ,local_eps.videoHeight, local_eps.EpisodeFileName  " +
                               "FROM online_episodes as online_eps LEFT OUTER JOIN local_episodes as local_eps " +
                               "ON online_eps.CompositeID=local_eps.CompositeID " +
                               "WHERE online_eps.SeriesID=" + _seriesId +
-                              (_season != -99 ? (" and online_eps.SeasonIndex=" + _season) : "");//also only get from one season
-            //"where online_eps.CompositeID = local_eps.CompositeID";
-
-            int counter = 0;
-            SQLiteDataReader reader = cmd.ExecuteReader();
-            while (reader.Read())
+                              (_season != null ? (" and online_eps.SeasonIndex=" + _season) : ""); //also only get from one season
+            return ReadList<WebEpisode>(sql, delegate(SQLiteDataReader reader)
             {
-                if (counter >= _start)
-                {
-                    if (_end != -99 && counter > _end) break;
-
-                    String compositeId = DatabaseHelperMethods.SafeStr(reader, 0);
-
-                    if (!allEpisodes.ContainsKey(compositeId))
-                    {//we don't have an entry for this episode yet -> add it
-                        WebEpisode episode = new WebEpisode();
-                        episode.IdSerie = _seriesId;
-                        episode.Id = DatabaseHelperMethods.SafeInt32(reader, 1);
-                        episode.Name = DatabaseHelperMethods.SafeStr(reader, 2);
-                        episode.SeasonNumber = DatabaseHelperMethods.SafeInt32(reader, 3);
-                        episode.EpisodeNumber = DatabaseHelperMethods.SafeInt32(reader, 4);
-                        episode.Watched = DatabaseHelperMethods.SafeInt32(reader, 5);
-                        episode.FirstAired = DatabaseHelperMethods.SafeDateTime(reader, 6);
-                        String bannerUrl = DatabaseHelperMethods.SafeStr(reader, 7);
-
-                        episode.BannerUrl = CreateBannerUrl(bannerUrl);
-
-                        episode.Rating = DatabaseHelperMethods.SafeFloat(reader, 8);
-                        episode.RatingCount = DatabaseHelperMethods.SafeInt32(reader, 9);
-
-                        if (!reader.IsDBNull(10))
-                        {
-                            episode.HasLocalFile = true;
-
-                            String filename = DatabaseHelperMethods.SafeStr(reader, 13);
-                            episode.FileName = filename;
-                        }
-                        else
-                        {
-                            episode.HasLocalFile = false;
-                        }
-
-                        allEpisodes.Add(compositeId, episode);
-                    }
-                    else
-                    {//episode has more than one file, we don't care atm -> only for full episode
+                string compositeId = DatabaseHelperMethods.SafeStr(reader, 0);
+                if (alreadyDone.Contains(compositeId))
+                    // episode has more than one file, we don't care atm -> only for full episode
+                    return null;
 
-                    }
+                // we don't haven an entry for this episode yet -> add it
+                WebEpisode episode = new WebEpisode();
+                FillBasicEpisode(reader, episode);
+
+                if (!reader.IsDBNull(10))
+                {
+                    episode.HasLocalFile = true;
+                    String filename = DatabaseHelperMethods.SafeStr(reader, 13);
+                    episode.FileName = filename;
+                } else
+                {
+                    episode.HasLocalFile = false;
                 }
-                counter++;
-            }
-            reader.Close(); reader.Dispose(); cmd.Dispose(); db.Close(); db.Dispose();
-            return new List<WebEpisode>(allEpisodes.Values);
+
+                return episode;
+            });
         }
 
+        public int GetEpisodesCount(int _seriesId)
+        {
+            return GetEpisodesCountForSeason(_seriesId, null);
+        }
 
+        public int GetEpisodesCountForSeason(int _seriesId, int? _season)
+        {
+            return ReadInt("Select COUNT(episodes.EpisodeId) " +
+                           "from online_episodes as episodes " +
+                           "where episodes.SeriesID=" + _seriesId +
+                           (_season != null ? (" and SeasonIndex=" + _season) : ""));
+        }
 
         public WebEpisodeFull GetFullEpisode(int _episodeId)
         {
-            DBLocations dbs = Utils.GetMPDbLocations();
-            SQLiteConnection db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(dbs.TvSeries));
-            try
-            {
-                db.Open();
-            }
-            catch (Exception)
-            {
-                return null;
-            }
-            SQLiteCommand cmd = db.CreateCommand();
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath) WHERE movieinfo.strTitle LIKE '" + title + "%'";
-            //cmd.CommandText = "SELECT files.idMovie,movieinfo.strGenre,movieinfo.strTitle,movieinfo.strPlot,(path.strPath || files.strFilename) as filename FROM files LEFT OUTER JOIN movieinfo ON (movieinfo.idMovie=files.idMovie) INNER JOIN path ON (path.idPath=files.idPath)";
-
-            cmd.CommandText = "Select online_eps.CompositeID, online_eps.EpisodeId, online_eps.EpisodeName, online_eps.SeasonIndex, online_eps.EpisodeIndex, online_eps.Watched, online_eps.FirstAired, " + //basic episode
+            string sql      = "Select online_eps.CompositeID, online_eps.EpisodeId, online_eps.EpisodeName, online_eps.SeasonIndex, online_eps.EpisodeIndex, online_eps.Watched, online_eps.FirstAired, " + //basic episode
                               "online_eps.thumbFilename, online_eps.Rating, online_eps.RatingCount, " + //basic episode
-                //"local_eps.IsAvailable, local_eps.videoWidth ,local_eps.videoHeight, " + //basic episode
                               "online_eps.Summary ,online_eps.GuestStars ,online_eps.Director ,online_eps.Writer ,online_eps.lastupdated ,online_eps.IMDB_ID ,online_eps.ProductionCode, " + //full episode
                               "online_eps.Combined_episodenumber ,online_eps.Combined_season ,online_eps.DVD_chapter ,online_eps.DVD_discid ,online_eps.DVD_episodenumber ,online_eps.DVD_season, " + //full episode
                               "online_eps.absolute_number ,online_eps.airsafter_season ,online_eps.airsbefore_episode ,online_eps.airsbefore_season, " + //full episode
                               "local_eps.EpisodeFileName ,local_eps.EpisodeIndex ,local_eps.SeasonIndex ,local_eps.IsAvailable ,local_eps.IsAvailable ,local_eps.localPlaytime, " + //full episode
                               "local_eps.videoWidth, local_eps.videoHeight, local_eps.VideoCodec, local_eps.VideoBitrate, local_eps.VideoFrameRate, " + //full episode
                               "local_eps.AudioCodec, local_eps.AudioBitrate, local_eps.AudioChannels, local_eps.AudioTracks, local_eps.AvailableSubtitles  " + //full episode
-                              "FROM online_episodes as online_eps LEFT OUTER JOIN local_episodes as local_eps " +
+                              "FROM online_episodes as online_eps " +
+                              "LEFT OUTER JOIN local_episodes as local_eps " +
                               "ON online_eps.CompositeID=local_eps.CompositeID " +
-                              "WHERE online_eps.EpisodeID=" + _episodeId;
+                              "WHERE online_eps.EpisodeID = " + _episodeId;
             //Todo: Remove "Removable" (changed to 2nd IsAvailable for now) since it doesn't exist anymore
+
             WebEpisodeFull episode = null;
-            SQLiteDataReader reader = cmd.ExecuteReader();
-            while (reader.Read())
+            ReadList<int>(sql, delegate(SQLiteDataReader reader)
             {
                 String compositeId = DatabaseHelperMethods.SafeStr(reader, 0);
 
                 if (episode == null)
-                {//we don't have an entry for this episode yet -> add it
+                {
+                    // we don't have an entry for this episode yet -> add it
                     episode = new WebEpisodeFull();
                     FillBasicEpisode(reader, episode);
                     FillFullEpisode(reader, episode);
 
-
                     if (!reader.IsDBNull(30))
                     {
                         episode.HasLocalFile = true;
                         WebEpisodeFull.WebEpisodeFile file = CreateEpisodeFile(reader);
                         episode.EpisodeFile = file;
-                    }
-                    else
+                    } else
                     {
                         episode.HasLocalFile = false;
                     }
-                }
-                else
-                {//episode has more than one file, atm only up to 2 files supported
+                } else
+                {
+                    // episode has more than one file, atm only up to 2 files supported
                     WebEpisodeFull.WebEpisodeFile file = CreateEpisodeFile(reader);
                     episode.EpisodeFile2 = file;
                 }
-            }
-            reader.Close(); reader.Dispose(); cmd.Dispose(); db.Close(); db.Dispose();
+
+                // creating a generic of a void isn't possible, so just return something
+                return 1;
+            });
+
             return episode;
         }
 
@@ -520,18 +348,12 @@ namespace GmaWebService.Code
             file.AudioTracks = DatabaseHelperMethods.SafeInt32(reader, 41);
             file.HasSubtitles = DatabaseHelperMethods.SafeBoolean(reader, 42);
 
-            /* "local_eps.EpisodeFileName ,local_eps.EpisodeIndex ,local_eps.SeasonIndex ,local_eps.IsAvailable ,local_eps.Removable ,local_eps.localPlaytime, " + //full episode
-                              "local_eps.videoWidth, local_eps.videoHeight, local_eps.VideoBitrate, local_eps.VideoFrameRate, " + //full episode
-                              "local_eps.AudioCodec, local_eps.AudioBitrate, local_eps.AudioChannels, local_eps.AudioTracks, local_eps.AvailableSubtitles  " + //full episode
-                      
-            */
             return file;
         }
 
         private String CreateBannerUrl(String _banner) {
             String path = Utils.GetWebBannerPaths()["tvseries"].Path;
             return path + "\\" + _banner.Replace('/', '\\');
-
         }
 
         private String CreateFanartUrl(String _banner)
@@ -540,8 +362,5 @@ namespace GmaWebService.Code
             return path + "\\" + _banner.Replace('/', '\\');
         }
         #endregion
-
-        #endregion
-
     }
 }
\ No newline at end of file
diff --git a/GmaWebService/Code/Query.cs b/GmaWebService/Code/Query.cs
new file mode 100644
index 0000000..900dc4c
--- /dev/null
+++ b/GmaWebService/Code/Query.cs
@@ -0,0 +1,34 @@
+﻿using System;
+using System.Data.SQLite;
+using GmaWebService.Code.Helper;
+
+namespace GmaWebService.Code
+{
+    internal class Query : IDisposable
+    {
+        SQLiteConnection db;
+        SQLiteCommand cmd;
+        public SQLiteDataReader Reader
+        {
+            get;
+            private set;
+        }
+
+        public Query(string databasePath, string query)
+        {
+            db = new SQLiteConnection(DatabaseHelperMethods.SQLiteConnStr(databasePath));
+            cmd = db.CreateCommand();
+            cmd.CommandText = query;
+            Reader = cmd.ExecuteReader();
+        }
+
+        public void Dispose()
+        {
+            Reader.Close();
+            Reader.Dispose();
+            cmd.Dispose();
+            db.Close();
+            db.Dispose();
+        }
+    }
+}
diff --git a/GmaWebService/GmaWebService.csproj b/GmaWebService/GmaWebService.csproj
index 9428232..e571b77 100644
--- a/GmaWebService/GmaWebService.csproj
+++ b/GmaWebService/GmaWebService.csproj
@@ -70,6 +70,7 @@
     </Content>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Code\Database.cs" />
     <Compile Include="Code\Helper\ShareUtils.cs" />
     <Compile Include="Code\MPPictures.cs" />
     <Compile Include="Code\MPVideo.cs" />
@@ -78,6 +79,7 @@
     <Compile Include="Code\MovingPictures.cs" />
     <Compile Include="Code\MPMusic.cs" />
     <Compile Include="Code\MPTvSeries.cs" />
+    <Compile Include="Code\Query.cs" />
     <Compile Include="WcfUsernameValidator.cs" />
     <Compile Include="WebHttpWithCustomExceptionHandling.cs" />
     <Compile Include="MediaAccessService.cs" />
