Commit c09b3aa
Changed files (5)
trunk
product
MyMoney
Infrastructure
caching
transactions2
trunk/product/MyMoney/Infrastructure/caching/IIdentityMap.cs
@@ -1,9 +1,11 @@
+using System;
using System.Collections.Generic;
namespace MoMoney.Infrastructure.caching
{
public interface IIdentityMap<TKey, TValue>
{
+ IEnumerable<TValue> all();
void add(TKey key, TValue value);
void update_the_item_for(TKey key, TValue new_value);
bool contains_an_item_for(TKey key);
@@ -23,6 +25,11 @@ namespace MoMoney.Infrastructure.caching
this.items_in_map = items_in_map;
}
+ public IEnumerable<TValue> all()
+ {
+ throw new NotImplementedException();
+ }
+
public void add(TKey key, TValue value)
{
items_in_map.Add(key, value);
trunk/product/MyMoney/Infrastructure/transactions2/ITransaction.cs
@@ -0,0 +1,11 @@
+using MoMoney.Domain.Core;
+
+namespace MoMoney.Infrastructure.transactions2
+{
+ public interface ITransaction
+ {
+ void add_transient<T>(T entity) where T : IEntity;
+ void commit_changes();
+ void rollback_changes();
+ }
+}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/transactions2/Session.cs
@@ -1,24 +1,67 @@
+using System;
+using System.Collections.Generic;
using MoMoney.Domain.Core;
+using MoMoney.Infrastructure.caching;
namespace MoMoney.Infrastructure.transactions2
{
- public interface ISession
+ public interface ISession : IDisposable
{
+ IEnumerable<T> all<T>();
void save<T>(T entity) where T : IEntity;
+ void flush();
}
public class Session : ISession
{
- IIdentityMapFactory factory;
+ readonly IIdentityMapFactory factory;
+ ITransaction transaction;
+ readonly IDictionary<Type, object> maps;
- public Session(IIdentityMapFactory factory)
+ public Session(IIdentityMapFactory factory, ITransaction transaction)
{
this.factory = factory;
+ this.transaction = transaction;
+ maps = new Dictionary<Type, object>();
+ }
+
+ public IEnumerable<T> all<T>()
+ {
+ return get_identity_map_for<T>().all();
}
public void save<T>(T entity) where T : IEntity
{
- factory.create_for<T>().add(entity.Id, entity);
+ create_map_for<T>().add(entity.Id, entity);
+ transaction.add_transient(entity);
+ }
+
+ public void flush()
+ {
+ transaction.commit_changes();
+ transaction = null;
+ }
+
+ public void Dispose()
+ {
+ if (null != transaction) transaction.rollback_changes();
+ }
+
+ IIdentityMap<Guid, T> get_identity_map_for<T>()
+ {
+ if (maps.ContainsKey(typeof (T)))
+ {
+ return (IIdentityMap<Guid, T>) maps[typeof (T)];
+ }
+ return create_map_for<T>();
}
+
+ IIdentityMap<Guid, T> create_map_for<T>()
+ {
+ var map = factory.create_for<T>();
+ maps.Add(typeof (T), map);
+ return map;
+ }
+
}
}
\ No newline at end of file
trunk/product/MyMoney/Infrastructure/transactions2/SessionSpecs.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using developwithpassion.bdd.contexts;
using MoMoney.Domain.Core;
using MoMoney.Infrastructure.caching;
@@ -13,15 +14,22 @@ namespace MoMoney.Infrastructure.transactions2
public class behaves_like_session : concerns_for<ISession, Session>
{
- context c = () => { factory = the_dependency<IIdentityMapFactory>(); };
+ context c = () =>
+ {
+ factory = the_dependency<IIdentityMapFactory>();
+ transaction = the_dependency<ITransaction>();
+ };
protected static IIdentityMapFactory factory;
+ protected static ITransaction transaction;
}
- public class when_saving_an_item_to_a_session : behaves_like_session
+ public class when_saving_a_transient_item_to_a_session : behaves_like_session
{
it should_add_the_entity_to_the_identity_map = () => map.was_told_to(x => x.add(guid, entity));
+ it should_add_the_item_to_the_current_transaction = () => transaction.was_told_to(x => x.add_transient(entity));
+
context c = () =>
{
guid = Guid.NewGuid();
@@ -32,13 +40,69 @@ namespace MoMoney.Infrastructure.transactions2
when_the(factory).is_told_to(x => x.create_for<ITestEntity>()).it_will_return(map);
};
- because b = () => { sut.save(entity); };
+ because b = () => sut.save(entity);
static ITestEntity entity;
static IIdentityMap<Guid, ITestEntity> map;
static Guid guid;
}
+ public class when_commiting_the_changes_made_in_a_session : behaves_like_session
+ {
+ it should_commit_all_the_changes_from_the_running_transaction =
+ () => transaction.was_told_to(x => x.commit_changes());
+
+ it should_not_rollback_any_changes_from_the_running_transaction =
+ () => transaction.was_not_told_to(x => x.rollback_changes());
+
+ because b = () =>
+ {
+ sut.flush();
+ sut.Dispose();
+ };
+ }
+
+ public class when_closing_a_session_before_flushing_the_changes : behaves_like_session
+ {
+ it should_rollback_any_changes_made_in_the_current_transaction =
+ () => transaction.was_told_to(x => x.rollback_changes());
+
+ because b = () => sut.Dispose();
+ }
+
+ public class when_retrieving_an_all_the_items_from_a_session_it_retrieve_all_the_items_from_the_cache :
+ behaves_like_session
+ {
+ it should_return_all_the_items_currently_loaded_in_the_cache = () => results.should_contain(entity);
+
+ it should_load_all_the_items_from_the_database = () =>
+ {
+ ///?how
+ };
+
+ context c = () => {
+ guid = Guid.NewGuid();
+ entity = an<ITestEntity>();
+ map = an<IIdentityMap<Guid, ITestEntity>>();
+
+ when_the(entity).is_told_to(x => x.Id).it_will_return(guid);
+ when_the(factory).is_told_to(x => x.create_for<ITestEntity>()).it_will_return(map);
+ when_the(map).is_told_to(x => x.all()).it_will_return(entity);
+ };
+
+ because b = () =>
+ {
+ sut.save(entity);
+ results = sut.all<ITestEntity>();
+ };
+
+ static IEnumerable<ITestEntity> results;
+ static ITestEntity entity;
+ static Guid guid;
+ static IIdentityMap<Guid, ITestEntity> map;
+ }
+
+
public interface ITestEntity : IEntity
{
}
trunk/product/MyMoney/MyMoney.csproj
@@ -297,6 +297,7 @@
<SubType>Component</SubType>
</Compile>
<Compile Include="Infrastructure\transactions2\IIdentityMapFactory.cs" />
+ <Compile Include="Infrastructure\transactions2\ITransaction.cs" />
<Compile Include="Infrastructure\transactions2\Session.cs" />
<Compile Include="Infrastructure\transactions2\SessionSpecs.cs" />
<Compile Include="Infrastructure\transactions\IUnitOfWorkRegistrationFactory.cs" />