How to migrate CSLA 4.0 TransactionManager to CSLA 6.0 or higher #3462
Replies: 3 comments 1 reply
-
We had this discussion on this forum and within our team some time ago. |
Beta Was this translation helpful? Give feedback.
-
The idea is to enable everyone to use standard coding patterns for this, rather than something CSLA-specific. With modern DI-based coding, you can create your database connection object as either a transient or scoped service. This is configured in Then in your data portal operation methods you can use the If you define the db connection as transient, you'll get a new instance every time you request one to be injected. If you define it as scoped, you'll get the same instance every time you request one to be injected - isolated within the root data portal invocation (in other words, your specific data portal operation will get that one connection for the root and all children). For "normal" data connections you'll probably want scoped, so you get the same connection/transaction for use by the root and all child object data portal operation methods. For something like logging or things out of band of the regular data work, you might also want a transient connection that exists on a per-injection basis. Nothing I'm discussing here (other than the |
Beta Was this translation helpful? Give feedback.
-
Hello Rocky, With your instructions and reading thread #2979, I made significant progress in migrating my project. In fact, I created a code generator that works for Oracle, Postgres, and SQL Server. It works quite well for fetching the object graph. I use Dependency Injection (DI) to inject interfaces of the Business Class and its direct children. Below is the DataPortal Fetch method and retrieving sequences to assign ID's to auto-generated properties. [Fetch]
private void Fetch(FilterCriteria filterCriteria, [Inject] IGrandFatherEditDal dal, [Inject] IChildDataPortal<ListFathers> listFathers)
{
GrandFatherEditDto GrandFatherEditDto = new GrandFatherEditDto();
Csla.Data.DataMapper.Map(filterCriteria, GrandFatherEditDto, true);
var data = dal.FetchObject(GrandFatherEditDto, filterCriteria.DbActionType, filterCriteria.DbOptionType, filterCriteria.CustomFilters);
using (BypassPropertyChecks)
{
Csla.Data.DataMapper.Map(data, this);
#region [Load_Child_Father_Properties]
if(filterCriteria.FatherFilterCriteria != null)
{
if(filterCriteria.FatherFilterCriteria.SetParentKeys)
{
filterCriteria.FatherFilterCriteria.GrandFatherId = data.GrandFatherId;
}
this.ListFathers = listFathers.FetchChild(filterCriteria.FatherFilterCriteria);
}
else
{
this.ListFathers = listFathers.FetchChild(new FatherEdit.FilterCriteria(true));
}
#endregion [Load_Child_Father_Properties]
}
BusinessRules.CheckRules();
} Where I'm stuck is in the Insert and Update methods because I understand I should place the database connection in a transaction in the DataPortal Insert method of the root Business Class and close the transaction when finishing operations in the children. I saw an example like the following: [Insert]
private Task DataPortal_Insert([Inject] IConnectionManager connectionManager, [Inject]IProjectRepository repository)
{
ProjectDTO data;
if (repository is null) throw new ArgumentNullException(nameof(repository));
data = LoadDTO();
using (connectionManager.StartTransaction())
{
data = repository.Insert(data);
LoadObjectChanges(data);
// Request that any children insert themselves as well
FieldManager.UpdateChildren(this);
// Commit the completed work
connectionManager.CommitTransactionAsync();
}
} My problem is that for each DataAccess project (Oracle, Postgres, or SQL Server), I create a DatabaseConnection object where I handle the database connection. It is a property of all my classes in the DAL, but that DatabaseConnection class is not available for my Library project to inject the connection because it is internally contained in the interface of the injected class using System.Data;
using Oracle.ManagedDataAccess.Client;
namespace DataAccess.Oracle
{
public class DatabaseConnection
{
private string _connectionString { get; set; }
OracleConnection _connection { get; set; }
public DatabaseConnection(string connectionString)
{
_connectionString = connectionString;
}
public OracleConnection GetConnection()
{
_connection = new OracleConnection(_connectionString);
_connection.Open();
return _connection;
}
public OracleTransaction GetTransaction()
{
if(_connection.State == ConnectionState.Closed)
{
_connection.Open();
}
return _connection.BeginTransaction();
}
}
} By doing this, I register the interfaces to be later injected: public static class ServiceManager
{
public static WebApplicationBuilder AddServices(this WebApplicationBuilder builder)
{
builder.Services.AddScoped(options => new DatabaseConnection(builder.Configuration.GetConnectionString("DatabaseConnectionString")));
#region [Application_Services]
builder.Services.AddScoped(typeof(Shared.Interfaces.IGrandFatherEditDal), typeof(DataAcess.Oracle.GrandFatherEditDal));
builder.Services.AddScoped(typeof(Shared.Interfaces.IFatherEditDal), typeof(DataAcess.Oracle.FatherEditDal));
#endregion [Application_Services]
return builder;
}
} Am I misunderstanding something, or what would be your suggestion on how to implement methods that require transaction handling to be able to roll back if something fails at any level of the object graph?" |
Beta Was this translation helpful? Give feedback.
-
Hello everyone,
I wanted to request your help because I'm in the process of migrating my application based on CSLA from version 4.0 to CSLA 6.0 or a higher version. My application frequently uses the TransactionManager class.
For example:
ctxConn = TransactionManager<OracleConnection, OracleTransaction>.GetManager(connString, false, "1234");
In the new version of CSLA, this class is marked as "Obsolete," and it is suggested to use dependency injection.
Since there are no examples in the CSLA source code that show how to migrate this class, I would greatly appreciate your assistance with an example or some guidance on how to modify my code for transaction handling in the new version of CSLA.
Thank you very much in advance.
Beta Was this translation helpful? Give feedback.
All reactions