I'm working on setting up a new MVC payment site with a dependency-injected database connection in a separate project, and experimenting with some new things as I do. Currently, I'm trying to load an existing transaction from the database, authorize the card payment, and then save the result back to the database. Simple and straightforward, but when I call SaveChanges()
, nothing gets saved, and I've run out of things to try.
The database interaction for this is handled by a CheckoutDataProvider
:
public class CheckoutDataProvider : ICheckoutDataProvider
{
private readonly CheckoutEntities _context;
public CheckoutDataProvider(CheckoutEntities _context)
{
this._context = _context;
}
public ITransaction GetTransactionDetails(Guid transactionId)
{
var trans = _context.Transactions.FirstOrDefault(x => x.CheckoutTransactionId == transactionId);
return trans; // It's OK if trans == null, because the caller will expect that.
}
public void AddAuthorization(ITransaction transaction, IAuthorizationHistory history)
{
try
{
var trans = (Transaction)transaction;
var hist = (AuthorizationHistory)history;
trans.AuthorizationHistories.Add(hist);
_context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
throw new InvalidDataException(ex.EntityValidationErrors.First().ValidationErrors.First().ErrorMessage, ex);
}
}
}
Transaction
and AuthorizationHistory
are EF objects and correspond directly to the database tables. CheckoutEntities
is the context, as injected by Ninject.
GetTransactionDetails()
works flawlessly. I give it the transactionId, I get the object, and then I use that data to run the card and generate the AuthorizationHistory
class. Then I call AddAuthorization()
to attach it to the transaction and save it to the database. But both the new AuthorizationHistory
object and any changes to the original Transaction
fail to save.
I can tell from inspecting the _context
object that it's not aware of any changes, and if I make changes withing GetTransactionDetails()
(before it gets returned as an interface) they will persist. So it looks like a problem with the casting (which makes me feel icky anyway, so I'd love to find out that that's the problem).
Am I missing something obvious? Is there something missing to get this to work? Is there a way to avoid the casting in AddAuthorization()
?
Probably you are not sharing the same DBContext Between GetTransactionDetails and AddAuthoritzation. Due to this reason Entity Framework is not able to track the changes.
Set the scope life of DBContext for web request, you can do it with Ninject with
.InRequestScope()
https://github.com/ninject/ninject/wiki/Object-Scopes , with this option the same DBContext will be used during a web request.