main
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using Gorilla.Commons.Infrastructure.Logging;
  5using gorilla.commons.utility;
  6
  7namespace momoney.database.transactions
  8{
  9    public interface ISession : IDisposable
 10    {
 11        T find<T>(Guid guid) where T : Identifiable<Guid>;
 12        IEnumerable<T> all<T>() where T : Identifiable<Guid>;
 13        void save<T>(T entity) where T : Identifiable<Guid>;
 14        void delete<T>(T entity) where T : Identifiable<Guid>;
 15        void flush();
 16        bool is_dirty();
 17    }
 18
 19    public class Session : ISession
 20    {
 21        ITransaction transaction;
 22        readonly IDatabase database;
 23        readonly IDictionary<Type, object> identity_maps;
 24        long id;
 25
 26        public Session(ITransaction transaction, IDatabase database)
 27        {
 28            this.database = database;
 29            this.transaction = transaction;
 30            identity_maps = new Dictionary<Type, object>();
 31            id = DateTime.Now.Ticks;
 32        }
 33
 34        public T find<T>(Guid id) where T : Identifiable<Guid>
 35        {
 36            if (get_identity_map_for<T>().contains_an_item_for(id))
 37            {
 38                return get_identity_map_for<T>().item_that_belongs_to(id);
 39            }
 40
 41            var entity = database.fetch_all<T>().Single(x => x.id.Equals(id));
 42            get_identity_map_for<T>().add(id, entity);
 43            return entity;
 44        }
 45
 46        public IEnumerable<T> all<T>() where T : Identifiable<Guid>
 47        {
 48            database
 49                .fetch_all<T>()
 50                .where(x => !get_identity_map_for<T>().contains_an_item_for(x.id))
 51                .each(x => get_identity_map_for<T>().add(x.id, x));
 52            return get_identity_map_for<T>().all();
 53        }
 54
 55        public void save<T>(T entity) where T : Identifiable<Guid>
 56        {
 57            this.log().debug("saving {0}: {1}", id, entity);
 58            get_identity_map_for<T>().add(entity.id, entity);
 59        }
 60
 61        public void delete<T>(T entity) where T : Identifiable<Guid>
 62        {
 63            get_identity_map_for<T>().evict(entity.id);
 64        }
 65
 66        public void flush()
 67        {
 68            this.log().debug("flushing session {0}", id);
 69            transaction.commit_changes();
 70            transaction = null;
 71        }
 72
 73        public bool is_dirty()
 74        {
 75            this.log().debug("is dirty? {0}", id);
 76            return null != transaction && transaction.is_dirty();
 77        }
 78
 79        public void Dispose()
 80        {
 81            if (null != transaction) transaction.rollback_changes();
 82        }
 83
 84        IIdentityMap<Guid, T> get_identity_map_for<T>() where T : Identifiable<Guid>
 85        {
 86            return identity_maps.ContainsKey(typeof (T))
 87                       ? identity_maps[typeof (T)].downcast_to<IIdentityMap<Guid, T>>()
 88                       : create_map_for<T>();
 89        }
 90
 91        IIdentityMap<Guid, T> create_map_for<T>() where T : Identifiable<Guid>
 92        {
 93            var identity_map = transaction.create_for<T>();
 94            identity_maps.Add(typeof (T), identity_map);
 95            return identity_map;
 96        }
 97
 98        public override string ToString()
 99        {
100            return "session: {0}".formatted_using(id);
101        }
102    }
103}