I have separated my application into two pieces. The first piece is my core functionality project. The other piece is the UI of the application. The core functionality should communicate with web services and interact with my SQLite databases.
In the core application I have four layers. These layers are:
- Business Layer
- Data Access Layer
- Data Layer
- Service Access Layer
I shall describe what each layer is in my application and where it is used for.
Business Layer
This layer holds my business models. It also holds some managers. These managers are important because they are communicating with the UI of the platform specific application. An example of such a manager is listed below:
public class AlbumManager
{
static AlbumManager ()
{
}
public static Album GetAlbum(int id) {
return DAL.AlbumRepository.GetAlbum (id);
}
public static IList<Album> GetAlbums (int venue_id)
{
return new List<Album> (DAL.AlbumRepository.GetAlbums (venue_id));
}
public static int SaveAlbums(IList<Album> albums) {
int count = 0;
foreach(var album in albums){
if (DAL.AlbumRepository.SaveAlbum (album) != 0)
count += 1;
}
return count;
}
public static int SaveAlbum (Album item)
{
return DAL.AlbumRepository.SaveAlbum(item);
}
public static int DeleteAlbum(int id)
{
return DAL.AlbumRepository.DeleteAlbum(id);
}
}
All it does is providing methods that are communicating with my repositories.
Data Access Layer
This layer is holding my repositories. One such repository looks like this:
public class AlbumRepository
{
DL.AppDatabase db = null;
protected static AlbumRepository me;
static AlbumRepository() {
me = new AlbumRepository();
}
protected AlbumRepository ()
{
db = new PhotoWapp.DL.AppDatabase (Constants.DatabaseFilePath);
}
public static Album GetAlbum(int id)
{
return me.db.GetItem<Album>(id);
}
public static IEnumerable<Album> GetAlbums (int venue_id)
{
return me.db.GetItems<Album>();
}
public static int SaveAlbum (Album item)
{
return me.db.SaveItem<Album>(item);
}
public static int DeleteAlbum(int id)
{
return me.db.DeleteItem<Album>(id);
}
}
I am just listing this class because you get an overview about how my application is behaving.
Data Layer
The data layer is communicating with the SQLite database. The most important class looks like this:
public class AppDatabase : SQLiteConnection
{
static object locker = new object ();
/// <summary>
/// Initializes a new instance of the <see cref="Tasky.DL.TaskDatabase"/> TaskDatabase.
/// if the database doesn't exist, it will create the database and all the tables.
/// </summary>
/// <param name='path'>
/// Path.
/// </param>
public AppDatabase (string path) : base (path)
{
// create the tables
CreateTable<Album> ();
}
public IEnumerable<T> GetItems<T> () where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return (from i in Table<T> () select i).ToList ();
}
}
public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
return Table<T>().FirstOrDefault(x => x.ID == id);
// Following throws NotSupportedException - thanks aliegeni
//return (from i in Table<T> ()
// where i.ID == id
// select i).FirstOrDefault ();
}
}
public int SaveItem<T> (T item) where T : BL.Contracts.IBusinessEntity
{
lock (locker) {
if (item.ID != 0) {
InsertOrReplace (item);
// Update (item);
return item.ID;
} else {
return Insert (item);
}
}
}
public int DeleteItem<T>(int id) where T : BL.Contracts.IBusinessEntity, new ()
{
lock (locker) {
#if NETFX_CORE
return Delete(new T() { ID = id });
#else
return Delete<T> (new T () { ID = id });
#endif
}
}
}
It has interaction with the database itself and nothing else.
Service Access Layer
And I have a service layer which should interact with a web service later on, but I have not yet written that webservice, so I am demonstrating this in-memory service.
public class MemoryAlbumService : Interfaces.AlbumService
{
public MemoryAlbumService ()
{
}
#region AlbumService implementation
public void GetAlbum (int id)
{
var album = new Album ();
album.ID = id;
album.Title = string.Format("Title {0}", id);
album.Description = string.Format("Beschrijving {0}", id);
album.Start_Of_Album = DateTime.Now.AddDays(-1);
album.End_Of_Album = DateTime.Now.AddDays(5);
album.Venue_Id = 1;
album.Thumbnail_Url = "http://testurl";
BL.Managers.AlbumManager.SaveAlbum (album);
OnFetchCompleted(EventArgs.Empty);
}
public virtual void OnFetchCompleted(EventArgs e) {
EventHandler handler = OnCompleted;
if(handler != null) {
handler (this, e);
}
}
public event EventHandler OnCompleted;
}
Per my understanding, this service layer should only return data. And it should not do anything else. Is this right? Because I wanted to do the following from my services:
- Get data
- Raise an event when the data has been fetched
- Then ask the manager for the updated data from the platform specific application.
I know my service isn't returning anything right now, but I just want to know if this method is valid how I am approaching this.
Does anybody has any valuable tips about solving this or any tips do to it in a separate way?
PS:
Somebody responded to my Stack Overflow post with the following answer:
Just retrieve data from the web service, nothing else. You can then create a facade which uses both the web service and the local service to keeps things in sync.