TransactionException saving children of a root object

TransactionException saving children of a root object

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


ktweedy posted on Monday, January 15, 2007

I am using CSLA 2.1 with my client Windows XP SP2 at home and my data located on a decdicated server at the hosting service location.

When I save the root object all is fine but when I try to open a second connection for saving the child collection I get the following error on the cn.Open() statement.

3:53:11 PM: MTGOSession 0: MTGOTraderController:TradePerformed Exception:DataPortal.Update failed (System.Transactions.TransactionException: The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025) ---> System.Runtime.InteropServices.COMException (0x8004D025): The partner transaction manager has disabled its support for remote/network transactions. (Exception from HRESULT: 0x8004D025)

I was able to insert the root using the TransactionType.TransactionScope setting.  I am able to also update the root object.  Seem all is related to the child objects Insert method.  Any ideas?  I am guess that MSDTC isn't talking through the fire walls correctly.  I check the MSDTC settings on the server an my client and all seems to be setup correctly. 

Here is the root Portal_Update code, the child collections Update methods and the child object insert method.

[Transactional(TransactionalTypes.TransactionScope)]

protected override void DataPortal_Update()

{

// TODO: update values

if (base.IsDirty)

{

using (SqlConnection cn = new SqlConnection(Database.ApplicationConnection))

{

cn.Open();

using (SqlCommand cm = cn.CreateCommand())

{

cm.CommandText = "updateTrade";

cm.Parameters.AddWithValue("@SDTradeID", _SDTradeID);

cm.Parameters.AddWithValue("@LastChanged", _timestamp);

SqlParameter param;

param = new SqlParameter("@DateUpdated", SqlDbType.DateTime);

param.Direction = ParameterDirection.Output;

cm.Parameters.Add(param);

DoInsertUpdate(cm);

// Get output parameters

_DateUpdated = new SmartDate((DateTime)(cm.Parameters["@DateUpdated"].Value));

}

}

}

// update child objects

_TradeItemsDealer.Update(this);

_TradeItemsTrader.Update(this);

}

 

 

internal void Update(BOTrade Trade)

{

this.RaiseListChangedEvents = false;

// update (thus deleting) any deleted child objects

foreach (BOTradeItem obj in DeletedList)

{

obj.DeleteSelf(Trade);

}

// now that they are deleted, remove them from memory too

DeletedList.Clear();

// add/update any current child objects

foreach (BOTradeItem obj in this)

{

if (obj.IsNew)

{

obj.Insert(Trade);

}

else

{

obj.Update(Trade);

}

}

this.RaiseListChangedEvents = true;

}

 

[Transactional(TransactionalTypes.TransactionScope)]

internal void Insert(BOTrade Trade)

{

// if we're not dirty then don't update the database

if (!this.IsDirty)

{

return;

}

using (SqlConnection cn = new SqlConnection(Database.ApplicationConnection))

{

cn.Open();

using (SqlCommand cm = cn.CreateCommand())

{

cm.CommandText = "addTradeItem";

// Setup to get back identity column

SqlParameter param = new SqlParameter("@SDTradeItemID", SqlDbType.Int);

param.Direction = ParameterDirection.Output;

cm.Parameters.Add(param);

cm.Parameters.AddWithValue("@SDTradeID", _SDTradeID);

cm.Parameters.AddWithValue("@SDAccountID", _SDAccountID);

cm.Parameters.AddWithValue("@MTGOAccountID", _MTGOAccountID);

cm.Parameters.AddWithValue("@MTGOAccountName", _MTGOAccountName);

cm.Parameters.AddWithValue("@InventoryCode", _InventoryCode);

cm.Parameters.AddWithValue("@DateCreated", _DateCreated.DBValue);

DoInsertUpdate(cm);

// Get identity

_SDTradeItemID = (int)cm.Parameters["@SDTradeItemID"].Value;

MarkOld();

}

}

}

 

 

ajj3085 replied on Monday, January 15, 2007

Why are you opening a second connection?  Is it to another database?

ktweedy replied on Monday, January 15, 2007

That is just the way the example project does it.  It opens seperate connection objects for the root and then does it again for the children.

Since I posted this I found a work around that was discuss in one of th topics on this site.

That is to pass down the connection object and not to open a new one, like how transaction objects were pass down to child objects in CSLA 1.0 and reused.

so now I say childList.Update(this, cn) passing the root object and the connection object.

Seems opening the second connection object kicks in the MSDTC and seems I either don't have something configured correctly or my firewall is interfering.

Thanks.

Copyright (c) Marimer LLC