Do you have recommendations on how to integrate Workflow Foundation 4 with DataObjects.Net? I'm currently in the process of choosing to use the workflow or not.

I'm seeing this problems for now:

  • Thread handling : From the documentation, if you don't use AsyncCodeActivity all your actions should be executed on the same thread, so we can use one session. But how should I pass it to the workflow? As an argument, with an extension?

  • Persistence : There is an implementation of a persistence store for SQL Server (with a dedicated schema) so this should work with DO. But how can I synchronize workflow persistence with DO.Net transactions to get a consistent state?

  • Arguments serialization : The arguments needs serialization to be persisted, so you can't pass Session, or Entities as arguments if the workflow is persisted.

PS: Just asking in case there is some expert here!

asked Oct 12 '10 at 10:29

olorin's gravatar image

olorin
358878792


One Answer:

I'm not quite familiar with WWF 4, so my answer will address just mentioned issues:

1. Thread handling

DO doesn't limit you to use just a single Session per thread. You can use any number of sessions in a single thread, but you should take into account that:

  • When you execute a method of any ISessionBound, DO "activates" its session - i.e. ensures any code inside this method (or invoked by this method) will get its Session as result of Session.Current and Session.Demand() calls. But one Session can be activated inside another one - the old one will be automatically restored on deactivation.
  • There is so-called session switching check. This topic explains this behavior; currently this behavior can be optionally turned of @ any Session: SessionOptions.AllowSwitching does this (earlier it was only possible to temporarily enable session switching with Session.Deactivate()).

Btw, upcoming v4.4 allows to disable automatic activation behavior for a particular session - we provide method overloads accepting Session as argument almost everywhere in this version, so generally, you'll be able to choose if it's convenient for you to rely on it, or not.

2. Persistence

As far as I can judge, this question is related to support of distributed transactions (support of System.Transactions) by DataObjects.Net - likely, you know this feature currently isn't supported (reason is obvious: there are no strong demand for it yet). So if this feature is necessary here, we're ready to prioritize it to make it available in few weeks.

3. Arguments serialization

True, you can't do that. I don't understand why it's necessary to pass Session as argument (likely, it should be provided by some other way), but that's clear that Entities and EntitySets are 100% candidates.

So I can suggest you to pass:

  • either string representation of Key objects (see Key.Format() and Key.Parse(...) methods),
  • or Ref(of T) structure - it's fully serializable, but to access its Value property, you must first ensure there is active Session (Session.Current != null). Also note this type is implicitly convertible from and to T type.

Also note that you can serialize and deserialize DisconnectedState along with the graph of entities (e.g. to persist it as part of workflow state). See MovableResult type from our WCF sample to understand how to do this.

Hopefully, this will help. If there will be any issues with proposed solutions (or others), I'll be willing to help.

answered Oct 12 '10 at 14:55

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

edited Oct 12 '10 at 14:59

Alex, i am curios what is and how to use Ref(of T) ? Have you somewhere an example about using it, when it is usedful?

(Oct 13 '10 at 01:31) Peter Šulek Peter%20%C5%A0ulek's gravatar image

It is a typed and serializable reference to any Entity. Like Key, but typed:

Ref<Book> bookRef1 = book; // Implicit cast works for T
Ref<Book> bookRef2 = book.Key; // And for Key as well

var cloner = Cloner.Default; // Type from Xtensive.Core, 
// its .Default instance relies on BinaryFormatter,
// although other ways of WCF serialization can be used here.

bookRef1 = cloner.Clone(bookRef1); // Serialize-deserialize
bookRef2 = cloner.Clone(bookRef2); // Serialize-deserialize
(Oct 13 '10 at 02:20) Alex Yakunin Alex%20Yakunin's gravatar image

Continuing:

Assert.AreEqual(bookRef1, bookRef2); // Equality works as well

Assert.AreEqual(book.Key, bookRef1.Key);
Assert.AreEqual(book.Key, bookRef2.Key);

using (book.Session.Activate()) // Normally this is already done
{
  Assert.AreSame(book, bookRef1.Value);
  Assert.AreSame(book, bookRef2.Value);
}
(Oct 13 '10 at 02:21) Alex Yakunin Alex%20Yakunin's gravatar image

And finally:

Book book1 = bookRef1; // Implicit cast to T, = ref.Value
Book book2 = bookRef2; // Implicit cast to T, = ref.Value

Key bookKey1 = bookRef1; // Implicit cast to Key, = ref.Key
Key bookKey2 = bookRef2; // Implicit cast to Key, = ref.Key
(Oct 13 '10 at 02:23) Alex Yakunin Alex%20Yakunin's gravatar image

Thanks Alex, and in which situations can be useful to use Ref(of T) ?

(Oct 13 '10 at 15:13) Peter Šulek Peter%20%C5%A0ulek's gravatar image

Thanks Alex and Peter for your ideas, I'll come back if I have more questions. It's useful to have a typed version of Key : this should be in manual ;)

(Oct 14 '10 at 02:14) olorin olorin's gravatar image

Alex: concerning Ref<t> you should a method/property to get Ref<t> from Entity or Key : the implicit cast is not easily discoverable by intellisense in Visual Studio and is a bit surprising when you read the code.

(Oct 14 '10 at 08:13) olorin olorin's gravatar image

Peter: If think the use of Ref<t> is when you need a serializable key to an entity (typically to use outside a transaction), and you want a typed key to get a constraint on the type of refered entity.

(Oct 14 '10 at 08:15) olorin olorin's gravatar image

Alex: Another remark on Ref<t> : Ref<myentity> myentityRef = null; does not compile.

(Oct 15 '10 at 05:37) olorin olorin's gravatar image

I'll add few more constructors there to make usage of implicit casts optional (Key and Value are already there).

Concerning null: the static type of null is object; use (Entity) null instead.

(Oct 15 '10 at 08:59) Alex Yakunin Alex%20Yakunin's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×574
×1
×1

Asked: Oct 12 '10 at 10:29

Seen: 2,274 times

Last updated: Oct 15 '10 at 08:59

powered by OSQA