User: mzywitza
Date: 2010/01/13 10:58 AM
Added:
/ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/
ConversationCanceledEventArgs.cs
Modified:
/ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/
ConversationScenarioTest.cs, ScopedConversationTests.cs
/ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/
IConversation.cs, ScopedConversation.cs
Log:
Finished IConversation.
File Changes:
Directory: /ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/
==========================================================================
File [modified]: ConversationScenarioTest.cs
Delta lines: +75 -5
===================================================================
---
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ScopedConversationTests.cs
2010-01-13 11:03:51 UTC (rev 6657)
+++
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ScopedConversationTests.cs
2010-01-13 17:58:00 UTC (rev 6658)
@@ -117,9 +117,9 @@
{
using (var c = new ScopedConversation())
{
- Assert.That(c.Canceled, Is.False);
+ Assert.That(c.IsCanceled, Is.False);
c.Cancel();
- Assert.That(c.Canceled);
+ Assert.That(c.IsCanceled);
}
}
@@ -128,15 +128,85 @@
{
using (var c = new ScopedConversation())
{
- Assert.That(c.Canceled, Is.False);
+ Assert.That(c.IsCanceled, Is.False);
c.Cancel();
- Assert.That(c.Canceled);
+ Assert.That(c.IsCanceled);
c.Restart();
- Assert.That(c.Canceled, Is.False);
+ Assert.That(c.IsCanceled, Is.False);
}
}
+ [Test]
+ public void ConversationIsCanceledAfterErrorInExecute()
+ {
+ using (var c = new ScopedConversation())
+ {
+ Assert.Throws<ApplicationException>(() =>
c.Execute(() => new PostLazy().SaveWithException()));
+ Assert.That(c.IsCanceled);
+ }
+ }
+ [Test]
+ public void ConversationIsCanceledAfterSilentError()
+ {
+ using (var c = new ScopedConversation())
+ {
+ c.ExecuteSilently(() => new
PostLazy().SaveWithException());
+ Assert.That(c.IsCanceled);
+ }
+ }
+ [Test]
+ public void TriggersEventWhenCanceling()
+ {
+
+ bool triggered = false;
+ using (var c = new ScopedConversation())
+ {
+ c.Canceled += (conv,args) => triggered = true;
+ c.Cancel();
+ }
+
+ Assert.That(triggered);
+ }
+
+ [Test]
+ public void TriggersWithRightArgsWhenCanceling()
+ {
+
+ bool triggered = false;
+ bool userCancel = false;
+ using (var c = new ScopedConversation())
+ {
+ c.Canceled += (conv, args) => { triggered =
true;
+ userCancel =
args.CanceledByUser; };
+ c.Cancel();
+ }
+
+ Assert.That(triggered);
+ Assert.That(userCancel);
+ }
+
+ [Test]
+ public void TriggersWithRightArgsWhenCancelingAfterException()
+ {
+
+ bool triggered = false;
+ Exception ex = null;
+ using (var c = new ScopedConversation())
+ {
+ c.Canceled += (conv, args) =>
+ {
+ triggered = true;
+ ex = args.Exception;
+ };
+ c.ExecuteSilently(()=>new
PostLazy().SaveWithException());
+ }
+
+ Assert.That(triggered);
+ Assert.That(ex, Is.Not.Null
+ .And.InstanceOf<ApplicationException>());
+ }
+
}
}
File [modified]: ScopedConversationTests.cs
Delta lines: +0 -0
===================================================================
Directory: /ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/
========================================================================
File [added]: ConversationCanceledEventArgs.cs
Delta lines: +30 -1
===================================================================
---
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/IConversation.cs
2010-01-13 11:03:51 UTC (rev 6657)
+++
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/IConversation.cs
2010-01-13 17:58:00 UTC (rev 6658)
@@ -80,6 +80,35 @@
/// <summary>
/// Whether the conversation is canceled
/// </summary>
- bool Canceled { get; }
+ bool IsCanceled { get; }
+
+ /// <summary>
+ /// Executes a block of code in the context of the
+ /// conversation. This allows to use ActiveRecord
+ /// without any scopes by doing all persistence calls
+ /// within Execute.
+ /// If an exception is caught, the conversation is
+ /// automatically canceled and the exception handed
+ /// down to the calling code.
+ /// </summary>
+ /// <param name="action">The code to execute</param>
+ /// <remarks>
+ /// This allows to use the interface directly, for example
+ /// if it is served through an IoC-Container.
+ /// </remarks>
+ void Execute(Action action);
+
+ /// <summary>
+ /// Executes a block of code. The conversation is canceled
+ /// if an exception occurs, but the exception will not be
+ /// handed to the calling code.
+ /// </summary>
+ /// <param name="action">The code to execute</param>
+ void ExecuteSilently(Action action);
+
+ /// <summary>
+ /// Fired when the conversation is canceled.
+ /// </summary>
+ event EventHandler<ConversationCanceledEventArgs> Canceled;
}
}
File [modified]: IConversation.cs
Delta lines: +58 -8
===================================================================
---
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/ScopedConversation.cs
2010-01-13 11:03:51 UTC (rev 6657)
+++
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/ScopedConversation.cs
2010-01-13 17:58:00 UTC (rev 6658)
@@ -45,7 +45,7 @@
private ConversationFlushMode flushMode;
- private bool canceled = false;
+ private bool _isCanceled = false;
private Dictionary<ISessionFactory, ISession> openedSessions =
new Dictionary<ISessionFactory,ISession>();
/// <inheritDoc />
@@ -58,7 +58,7 @@
{
foreach (var session in openedSessions.Values)
{
- if (canceled)
+ if (_isCanceled)
session.Transaction.Rollback();
else
{
@@ -75,9 +75,16 @@
/// <inheritDoc />
public void Cancel()
{
- canceled = true;
+ DoCancel(true, null);
}
+ private void DoCancel(bool userCanceled, Exception
exceptionCaught)
+ {
+ _isCanceled = true;
+ var args = new
ConversationCanceledEventArgs(userCanceled, exceptionCaught);
+ TriggerCanceled(args);
+ }
+
/// <inheritDoc />
public void Flush()
{
@@ -92,7 +99,7 @@
public void Restart()
{
ClearSessions();
- canceled = false;
+ _isCanceled = false;
}
/// <inheritDoc />
@@ -113,11 +120,33 @@
}
/// <inheritDoc />
- public bool Canceled
+ public bool IsCanceled
{
- get { return canceled; }
+ get { return _isCanceled; }
}
+ /// <summary>
+ /// Executes the action.
+ /// </summary>
+ /// <param name="action">The action</param>
+ /// <param name="silently">Whether to throw on exception</param>
+ public void Execute(Action action, bool silently)
+ {
+ try
+ {
+ using (new ConversationalScope(this))
+ {
+ action();
+ }
+ }
+ catch (Exception ex)
+ {
+ DoCancel(false, ex);
+ if (!silently)
+ throw;
+ }
+ }
+
/// <inheritDoc />
public ISession GetSession(ISessionFactory factory,
IInterceptor interceptor)
{
@@ -129,11 +158,11 @@
private void AssertNotCanceled()
{
- if (canceled)
+ if (_isCanceled)
{
throw new ActiveRecordException(
"A session was requested from a
conversation that has "+
- "been already canceled. Please check
that after the "+
+ "been already _isCanceled. Please check
that after the "+
"cancellation of a conversation no more
"+
"ConversationalScopes are opened using
it.");
}
@@ -149,5 +178,26 @@
NHibernate.FlushMode.Never;
openedSessions.Add(factory,session);
}
+
+ /// <inheritDoc />
+ public void Execute(Action action)
+ {
+ Execute(action,false);
+ }
+
+ /// <inheritDoc />
+ public void ExecuteSilently(Action action)
+ {
+ Execute(action, true);
+ }
+
+ /// <inheritDoc />
+ public event EventHandler<ConversationCanceledEventArgs>
Canceled;
+
+ private void TriggerCanceled(ConversationCanceledEventArgs args)
+ {
+ if (Canceled != null)
+ Canceled(this, args);
+ }
}
}
File [modified]: ScopedConversation.cs
Delta lines: +26 -0
===================================================================
---
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ConversationScenarioTest.cs
2010-01-13 11:03:51 UTC (rev 6657)
+++
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ConversationScenarioTest.cs
2010-01-13 17:58:00 UTC (rev 6658)
@@ -165,7 +165,33 @@
}
}
+ [Test]
+ public void CanUseIConversationDirectly()
+ {
+ ArrangeRecords();
+ using (IConversation conversation = new ScopedConversation())
+ {
+ BlogLazy blog = null;
+ conversation.Execute(() => { blog =
BlogLazy.FindAll().First(); });
+
+ Assert.That(blog, Is.Not.Null);
+ Assume.That(blog.Author, Is.EqualTo("Markus"));
+
+ // Lazy access
+ Assert.That(blog.PublishedPosts.Count,
Is.EqualTo(1));
+
+ blog.Author = "Anonymous";
+
+ conversation.Execute(() => blog.Save());
+
+ }
+
+ Assert.That(BlogLazy.FindAll().First().Author,
Is.EqualTo("Anonymous"));
+ }
+
+
+
private void ArrangeRecords()
{
--
You received this message because you are subscribed to the Google Groups
"Castle Project Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-commits?hl=en.