Hello,
I have a ER object called Message....
I am creating and saving the object like this in a unit test...
[TestClass]
public class MessageUnitTests
{
[TestMethod]
public void NewMessageCreate_succeeds()
{
var m = ULMOnlineMessageManager.BizObjects.Message.NewMessage();
m.Id = 6;
m.AccountNumber = string.Empty;
m.Active = true;
m.Text = "This is a test message!";
m.ActiveDate = Csla.SmartDate.StringToDate("9/13/2012");
m.IsRichText = false;
if (m.IsSavable)
{
m = m.Save();
}
}
}
As expected the Save method is calling into my DataPortal_Insert method...
protected override void DataPortal_Insert()
{
using (var ctx = TransactionManager<SqlConnection, SqlTransaction>.GetManager("MyDatabase"))
{
using (var cmd = new SqlCommand(
"INSERT INTO Messages (ID,AccountNumber,ActiveDate,Message,Active,IsRichText) VALUES(@ID,@AccountNumber,@ActiveDate,@Message,@Active,@IsRichText)"
, ctx.Connection))
{
cmd.Transaction = ctx.Transaction;
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@ID", Utility.NullIfZero(ReadProperty<int>(IdProperty))).DbType = DbType.Int32;
cmd.Parameters.AddWithValue("@AccountNumber", Utility.NullIfEmpty(ReadProperty<string>(AccountNumberProperty))).DbType = DbType.String;
cmd.Parameters.AddWithValue("@ActiveDate", ReadProperty<DateTime>(ActiveDateProperty)).DbType = DbType.DateTime;
cmd.Parameters.AddWithValue("@Message", Utility.NullIfEmpty(ReadProperty<string>(TextProperty))).DbType = DbType.String;
cmd.Parameters.AddWithValue("@Active", ReadProperty<bool>(ActiveProperty)).DbType = DbType.Boolean;
cmd.Parameters.AddWithValue("@IsRichText", ReadProperty<bool>(IsRichTextProperty)).DbType = DbType.Boolean;
var result = cmd.ExecuteNonQuery();
}
}
}
The ExecuteNonQuery returns without error.
but when I query the database the new record is not inserted.
I know that I am hitting the correct database (sql trace shows the transaction...I can take the code from the transaction and run it in a new query window and it works. )
The behavior is as if the transaction is being rolled back.
Ideas?
Seth
Why won´t you use the bultin transaction support? (TransactionalAttribute on DataPortal_XYZ) or TransactionScope?
The transaction is rolled back because you never call commit on the transaction.
(cmd.Transaction = ctx.Transaction).
IE: You use a manual transaction in your DAL.
If you do not call Commit on the transaction the transaction will rollback when it goes out of scope.
Jonny
This is all experimental...I pieced together a sample from old code and new code using samples. Not sure how it all works. I worked in csla 3.02 several years ago and now I am trying to wrap my brain around the 4+ stuff.
I would prefer to use the Transactional attribute. So do I add the transactional attribute and then I remove the cmd.Transaction = ctx.Transaction. Are they the only changes I need to make?
Seth
I would rather use a ConnectionManager (than the TransactionManager) then the described changes.
Doing what I just said returns an error about doing a commit transaction without having a corresponding Begin Transaction. How do I do this with the transactional attribute?
Seth
Use ConnectionManager instead of TransactionManager.
Thanks...that did it...for posterity...here is the change I made (it is a different xyz method from what I have in the question...)
[Transactional]
protected override void DataPortal_DeleteSelf()
{
using (var ctx = ConnectionManager<SqlConnection>.GetManager("MyDatabase"))
{
using (var cmd = new SqlCommand(
"DELETE FROM Messages WHERE ID=@ID"))
{
cmd.Connection = ctx.Connection;
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("@ID", Utility.NullIfZero(ReadProperty<int>(IdProperty))).DbType = DbType.Int32;
cmd.ExecuteNonQuery();
}
}
}
Copyright (c) Marimer LLC