Is there a way to pass the parent DataContext to the child?

Is there a way to pass the parent DataContext to the child?

Old forum URL: forums.lhotka.net/forums/t/6249.aspx


raz0rf1sh posted on Sunday, January 25, 2009

I have two libraries in separate projects. I have the following setup:

Library1.Class1 EditableRoot

Library2.Class1 EditableChildList
Librart2.Class2 EditableChild

Each has their own separate DataContext, but only for design purposes. When running I would like for the child to just use the parent's DataContext. Right now I have:

[Transactional(TransactionalTypes.TransactionScope)]
private void Child_Insert(CreativeLogic.Gandalf.ISource parent)
{
using (var ctx = Csla.Data.ContextManager
.GetManager(Database.ApplicationConnection, false))
{
var data = new Haldir.Data.Label();

data.Name = this.ReadProperty(NameProperty);
data.Source = this.ReadProperty(SourceProperty);
data.SourceId = this.ReadProperty(SourceIdProperty);
data.CreatedBy = new Guid(Csla.ApplicationContext.User.Identity.Name);
data.CreatedDate = DateTime.Now;

ctx.DataContext.Labels.InsertOnSubmit(data);

ctx.DataContext.SubmitChanges();

this.LoadProperty(CreatedByProperty, data.CreatedBy);
this.LoadProperty(CreatedDateProperty, data.CreatedDate);
}
}

I would really like the ctx to be that of the parent? Is this possible and/or is there a better way?

I want to reuse the Library2 in multiple projects which is why I have it isolated in it's own project.

rsbaker0 replied on Sunday, January 25, 2009

I don't know if CSLA directly supports this, but I manually manage transactions and make the "transaction context" available across the entire application by (very carefully) storing it in the LocalContext object dictionary that CSLA manages for you.

So, you could store your parent data context in the LocalContext when it is created, and then any data operations that occur at arbitrary nesting depths could retrieve it and use it, and then when the parent is finished, it could remove the parent data context from the LocalContext.

I say "very carefully" because it is imperative that you not leave an old context in place if an error or exception occurs. So, I encapsulate all this in a class that implements IDisposable and do the clean up in dispose, and then only use said object in a using() block or try/catch/finally block.

There may be implications of using the same data context across multiple methods that each have their own TranactionScope attribute, so I'm not sure if there are any gotchas there.

(The LocalContext is maintained per-thread, so my understanding was that this would allow multiple simultaneous transactions -- or data contexts in your case -- to be stored using the same name, one per thread, in cases where multiple threads might be active, e.g. ASP.NET or using a web service data portal)

RockfordLhotka replied on Sunday, January 25, 2009

rsbaker0:

I don't know if CSLA directly supports this, but I manually manage transactions and make the "transaction context" available across the entire application by (very carefully) storing it in the LocalContext object dictionary that CSLA manages for you.

This is exactly what the ConnectionManager, ContextManager and similar types do for you in CSLA .NET 3.6.

There should never be a need to share one of these manager objects across your application, because these objects are designed to automatically reuse the same underlying connection/context/etc.

lukky replied on Sunday, January 25, 2009

Hi,

If you use the ContextManager, it will actually reuse the same DataContext as the Parent's DataContext.

ContextManager uses reference counting to keep track of how many times the DataContext is being used. So, in the Parent's "using" block, you create a new DataContext. When you reach the Child's "using" block, you are returned the same DataContext, but the ContextManager now has a refcount of 2. When you exit the Child's "using" lock, the refcount is decreased, and when you exit the Parent's "using" block, the refcount reaches 0, so the DataContext is disposed.

In your code, you call SubmitChanges() in the Child_XXX method. Since you reuse the Parent's context, it might be best to call SubmitChanges() only in the Parent's DataPortal_XXX method.

regards.

Copyright (c) Marimer LLC