Work with database transactions in a functional manner in C# - c#

I was looking at this kind of code and wondering, is there anything that can be improved if you approach from functional programming perspective?
You don't have to strictly re-implement my example to answer, if you have different example involving Transactions, that would be great.
using (var unitOfWork = _uowManager.Begin())
{
_paymentRepository
.InsertOrUpdate(payment); // Returns payment instance
// Being executed to get Payment.Id
_uowManager
.SaveChanges();
_otherRepository
.OtherMethod(payment.Id); // Could be changed as necessary
unitOfWork
.Complete()
}
Code above is based on ASP.NET Boilerplate and Entity Framework if it helps.

I think that creating transactional monad is a great way to handle this. Doesn't matter how much FP is in C#, this creates a lot of benefits:
single, global, unified way to handle transactions
don't repeat yourself, write this class once and don't recreate transaction logic n times for each controller function
you can create this class as interface and mock it in integration tests, for example, to rollback transaction, so your tests don't impact the database state
I use something like this:
public class Tx
{
public DbConnectionExtra _connection { get; set; } // class which has DbTransaction and DbConnection combined
public T UseTx<T>(Func<T> fnToCall)
{
try
{
_connection.BeginTransaction();
var result = fnToCall();
_connection._transaction.Commit();
_connection._transaction.Dispose();
return result;
}
catch
{
_connection._transaction.Rollback();
_connection._transaction.Dispose();
throw;
}
}
}

Related

ASP MVC Entity Framework Database context and classes

In my asp mvc Framework project, using EF, I have some objects (from classes) whose fields store data coming from my database.
My question is :
How to populate these fields, or manage methods of these objects using a dbcontext variable ?
Sol 1: Is it better to use each time I need a connection with db in my classes with the instruction (using (resource), see below ) ?
Sol 2: Is it betterI to code a singleton class to use one instance of the context ?
Sol 3: Or should I use another way for the links beetween my classes and the database ?
What is the best method considering performances and code quality.
Thanks for your attention .
Solution 1
public class Test
{
private T1 a;
private T2 b;
public Test()
{}
public void CreateFrom (int id)
{
using (var db=new WebApplicationMVCTest.Models.dbCtx())
{
a=db.T1s.Find(id);
b= db.T2s.Find(a.id2);
}
}
Solution 2:
public class DbSingleton
{
private static dbCtx instance;
private int foo;
private DbSingleton ()
{}
public static dbCtx Current
{
get
{
if (instance == null)
{
instance = new dbCtx();
}
return instance;
}
}
public static void Set (dbCtx x)
{
if (instance==null)
{
instance = x;
}
}
}
For a web project, never use a static DbContext. EF DbContexts are not thread safe so handling multiple requests will lead to exceptions.
A DbContext's lifespan should only be as long as it is needed. Outside of the first time setup cost when a DbContext is used for the first time, instantiating DbContexts is fast.
My advice is to start simple:
public ActionResult Create(/* details */)
{
using (var context = new AppDbContext())
{
// do stuff.
}
}
When you progress to a point where you learn about, and want to start implementing dependency injection applications then the DbContext can be injected into your controller / service constructors. Again, from the IoC container managing the DbContext, the lifetime scope of the Context should be set to PerWebRequest or equivalent.
private readonly AppDbContext _context;
public MyController(AppDbContext context)
{
_context = context ?? throw new ArgumentNullException("context");
}
public ActionResult Create(/* details */)
{
// do stuff with _context.
}
The gold standard for enabling unit testing would be injecting a Unit of Work pattern and considering something like the Repository pattern to make your dependencies easier to unit test.
The best advice I can give you starting out with EF and MVC is to avoid the temptation to pass Entities between the controller (server) and the UI. (views) You will come across dozens of examples doing just this, but it is a poor choice for performance, it also hides a LOT of land mines and booby traps for both performance, exceptions, and data security issues. The most important detail is that when the UI calls the controller passing what you expect will be an entity, you are not actually getting an entity, but a de-serialized JSON object cast to an entity. It is not an entity that is tracked by the DbContext handling the request. Instead, get accustomed to passing view models (serializable data containers with the data the view needs or can provide) and IDs + values where the controller will re-load entities to update the data only as needed.

EntityFrameworkCore swap DbConnection (add Transaction)

I have large DB model (hundred of tables) split to multiple EntityFrameworkCore DbContexts. Is is a quite common use case when I modify multiple entities in two (or more) different DbContexts, but I need to commit this operations withing a single transaction.
I use a IReporitory pattern where I get injected into Controller an instance of ISomeRepository implementation which looks like:
[HttpPost]
public asycn Task DoSomeWorkAsync()
{
using (var transaction = this.IEmployeesRepository.BeginTransaction())
{
// do some work
await this.IEmployeesRepository.SaveChangesAsync();
// do another work
await this.IPayrollRepository.SaveChangesAsync();
}
}
An EmployeeDbContext implements an IEmployeeRepository interface, PayrollDbContexts implements IPayrollRepository.
I end up with error:
System.InvalidOperationException: The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used.
There exists very handy documentation, which basically solves the problem.
Cool, but I am not able to create a new instance of EmployeeDbContext, as described in documentation, because I am working with abstraction - interface only. I am looking for some method how to change / swap / inject / replace a DbConnection in existing DbContext.
I was thinking of implementing Clone method like
[HttpPost]
public asycn Task DoSomeWorkAsync()
{
using (var transaction = this.IEmployeesRepository.BeginTransaction())
{
await this.IEmployeesRepository.SaveChangesAsync();
var payrollRepoClone = IPayrollRepository.Clone(transaction);
await payrollRepoClone.SaveChangesAsync();
}
}
and then I would do
public class PayrollDbContext : DbContext, IPayrollRepository
{
private readonly DbConnection dbConnection;
public PayrollDbContext Clone(DbTransaction tran)
{
return new PayrollDbContext(tran.GetDbTransaction.Connection);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(dbConnection);
}
}
but I am trying to avoid this kind of tight coupling with SQL Server, because currently UseNpgSql is called in IoC in Service container where I resolve IPayrolRepository instance. And UseInMemoryDatabase in unit tests. This would crash my tests (or at least will require some dirty if/else in OnConfiguring)
Do you have any hints how to inject transaction or dbConnection to existing DbContext?
Thanks

How to dispose the ContextDB class automatically after any query done using it

ASP.NET MVC 5 Project.
I know that the best practice of using EF context object as the following
using(var context = new ContextDB())
{
}
But I am working with a large existing project which not used this practice.
the project using the following pattern
public abstract class BaseService
{
private static ContextDB _data { get; set; }
public static ContextDB Data
{
get
{
if (_data== null)
_data= new ContextDB();
return _data;
}
}
}
Actually, because of this pattern, I am receiving this exception (sometimes, not always)
So to solve this I have to change all the code which is using the shared Data
property and replace it with the new instance of ContextDB as I mentioned in the beginning of the question.
The problem that this is a very large modification, and I will not be allowed to do that modification.
The Question, can I solve this problem without changing a ton of code, In another word, can I solve the problems with modifications done only inside the BaseService class, for example, Is there any event which I could handle to know if any query is executed and then dispose of the ContextDB
here is the pseudo-code of the idea in my mind
public abstract class BaseService
{
public static ContextDB Data
{
get
{
ContextDB _data= new ContextDB();
_data.SqlQueryExecuted += () => { this._data.dispose(); }
return _data;
}
}
}
NOTE: the SaveChanged event is not suitable, because not all of the query are updating or inserting.
I may use following solution.
In Global.asax
Begin Request : Create Instance of your dbContext. Store it in HttpContext.Current.Items.
End Request : Grab the context and close / dispose connection.
Another better solution is to use DI. Dependency Injection and limit the scope of your instance. There are many way Like Singleton, PerRequest etc.

Unit Testing Job Component C#

I'm trying to bring a legacy project under test. The code was written in such a way that it is generally testable, however some of the third party dependencies were not. I'm trying to wrap my head around how to unit test something that looks like this:
class InsightEmailJob : NHibernateJob
{
public IInsightEmailService InsightEmailService { get; set; }
public IReportService ReportService { get; set; }
public ITemplatedNotifier TemplatedNotifier { get; set; }
public string ReplyEmail { get; set; }
public string ReplyName { get; set; }
public InsightEmailJob(ISession session,
ILog log,
IInsightEmailService insightEmailService,
IReportService reportService,
ITemplatedNotifier templatedNotifier,
SystemReplyEmailSpec systemReplyEmailSpec)
: base(session, log)
{
InsightEmailService = insightEmailService;
ReportService = reportService;
TemplatedNotifier = templatedNotifier;
ReplyEmail = systemReplyEmailSpec.ReplyEmail;
ReplyName = systemReplyEmailSpec.ReplyName;
}
public int AccountID{ get; set; }
private Account mAccount;
public Account Account
{
get
{
if (this.mAccount == null)
{
mAccount = this.InsightEmailService.Get<Account>(AccountID);
}
return mAccount;
}
}
protected override void DoWork(JobExecutionContext context)
{
var insightEmail = InsightEmailService.FindAndIncrementEmailForAccount(Account);
var report = ReportService.LoadMultiReportByName(insightEmail.ReportName);
var reportData = ReportService.Execute(report, new ParameterValuesDictionary(Account, DateTime.Now.AddDays(-7), DateTime.Now, 0));
var templateData = new Hashtable {{"data", reportData}, {"account", Account}};
foreach (var u in Account.Users.Where(x => x.Notify))
{
TemplatedNotifier.Send(u.UserName, ReplyName, ReplyEmail, insightEmail.TemplateName, templateData);
}
}
}
I understand that a lot of people would suggest using Mocks or Stubs to pass in instead of the interfaces, however I'm a little confused as to how this is actually beneficial. It seems that this would just ensure that the appropriate methods are called, which strikes me as somewhat vacuous, and far too coupled with the implementation of the job to be a really valid test. Ultimately the question becomes, how do you unit test something that returns no values and really only causes side effects without just testing that its implemented the way you say it is?
Unit tests are written to prove your implementations work correctly. If your test code is getting too complex and things are becoming harder to mock, implementation code is probably getting more complex and harder to understand as well.
When you decide there is too much work in mocking dependencies, you should reconsider your design and aim to refactor it to a simpler form.
Just by looking at your constructor we can see that it's probably doing too much work. You have 6 dependencies and you will have to mock all of them to write valid unit tests. I don't think you have enough abstractions here because you have to deal with NHibernate sessions, some reporting service and send an email.
Repository Pattern is a common pattern for abstracting data access code. You also should move email sending part to another class and use its interface here.
It's pretty easy to mock methods that don't have a return value. By mocking these method calls you prove that your class is using external dependencies correctly.You can write asserts for parameter values and how many times it is called to validate your code.
Anyway here's an example of how you can mock a method in Moq
insightEmailService.Setup(mock => mock.FindAndIncrementEmailForAccount(It.IsAny<Account>()))
.Verifiable();
When you do unit testing, you are just testing unit. It means under a given external dependencies , how is the unit (example a method calling methods from other services). Therefore , you need to see for various condition of the external dependency if your code under tests behaves right.
For methods that return nothing there are a number of ways to verify this
if you are using Mocking framework ,say for example Moq, you can use Verify to make sure that external methods are call with appropriate parameters.
You can verify what is passed to external methods using callbacks ( moq has good callback mechanism)

TransactionScope functions

Working on Transactions in .net. Had a question on flowing transactions through sub functions. Do I need to use dependent transactions if the object context is common across the sub - methods?
For example, in the following code - I declare the object context in the constructor of my class (not sure if this is best practice)
public class EmployeeRepository
{
private EmployeeContext ec;
public EmployeeRepository()
{
objectContext = new EmployeeContext();
}
public InitTransaction(EmployeeEntity emp1)
{
using (TransactionScope transaction = new TransactionScope())
{
try
{ ec.employees.AddObject(emp1);
SubFunction1();
ec.SaveChanges();
}
catch
{
//catch
}
}
//commit the transaction here
ec.AcceptAllChanges();
}
public SubFunction1()
{
//some processing
//using same object context
ec.someother.AddObject(someobject);
ec.SaveChanges();
}
}
I want the subfunctions to be a part of the transactions as well?
In this case should I use a dependent transaction within SubFunction1 even though I am using the same object context? Or Should I add a
using (TransactionScope transaction = new TransactionScope());
within SubFunction1. Pointers in the right direction would be greatly appreciated.
Transaction Scopes can be nested (they work similar to the SQL ##TRANCOUNT mechanism), so you could in theory use TransactionScopes in your Repository, e.g. to keep parent : child table relationships ACID, but also in your Business / Service layers as well (e.g. to have a Distributed Transaction across multiple entities, possible across multiple Databases, and even across other resources such as Message Queues and Transactional file systems.
Note that the default isolation level of TransactionScope is Read Serializable - this can lead to locking / deadlocks.
You can consider using Dependency Injection to pass around the same ObjectContext so you can avoid the TransactionScope.
Instead of creating Context inside the Repository inject it through constructor.
public class EmployeeRepository
{
private EmployeeContext ec;
public EmployeeRepository(EmployeeContext objectContext)
{
ec = objectContext;
}
}
Take a look at this answer

Categories

Resources