Folks,
Envrionment: ASP.NET MVC 4, Razor
I am using SimpleMembership provider for my web application. When the user requests for registration, I need to call WebSecurity.CreateUserAndAccount and also update some other tables. The whole operation has to be transactional. Here is what I am thinking:
using (UsersContext ctx = new UsersContext()) {
using (TransactionScope scope = new TransactionScope()) {
// The following call creates its own context but will call ctx.SaveChanges() internally
WebSecurity.CreateUserAndAccount(...);
// update some other tables using ctx
...
ctx.SaveChanges();
scope.complete();
}
}
I have a feeling this should work. However, I would like to get your expert opinion on whether there is a better way.
Thank you in advance for your help.
Regards,
Peter
TransactionScope is the best way to make it all happen inside the same transaction, but be careful with how your connection strings are defined (and test on Azure if that's where you are deploying it to) as the DTC may get involved and cause you problems in some scenarios (example)
The alternative would be to inherit from SimpleMembershipProvider and override CreateUserAndAccount, as that is all that WebSecurity calls. You could then do all the work inside a single context by duplicating and extending the SimpleMembershipProvider code.
Related
I'm using Entity Framework 5.0 and MVC4. I have couple of domains. Each of them has its own DbContext (which uses appropriate tables), repository and service. I also implemented UnitOfWork.
Handling specific flow in transaction inside one service for specific domain is simple. I'm doing some operations on tables and at the end I'm invoking UnitOfWork.Save, which behaves as Transaction.Commit.
But lets assume I have a case in which I have to invoke operations for two different domains and this two operations must be put inside one transaction. I have access to services for domains from controller so this actions are invoked from there. At the moment I can see three solutions:
I must have UnitOfWork in controller and call Save method at the end (I don't like this idea).
Create some service in which I will have UnitOfWork and access to both services (actually it is the same solution as above, but I'm moving logic to separate class)
I have to create additional TransactionScope inside controller and commit it at the end
Please let me know what option you think is the best. If you have any other than the three above, let me know. Or maybe something is wrong with my concept? I mean domains and their db contexts?
Assuming your UnitOfWork implementation supports normal Transactions in .NET, you can do the following and they should enroll in the currently running transaction.
protected TransactionScope CreateTransactionScope()
{
var options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.MaximumTimeout;
return new TransactionScope(TransactionScopeOption.Required, options);
}
using (var scope = this.CreateTransactionScope())
{
// do operations with context 1
// do operations with context 2
scope.Complete();
}
I am trying to figure out the best way to design an MVC4 application with DI via Ninject.
When the user comes to the system, they are presented with a login where they can select one of many databases. Each database is a separate catalog on a database server. What I need to do is inject a repository with the database connection details once the user is logged in. The type of repository does not change, just the connection details.
I have found this post which I could make work, but I am not sure if it is the best approach for my situation. What other options have people used with success?
Problem solved. As I am wishing to pass the connection string in the constructor for my concrete repository I can use the following Ninject WithConstructorArgument:
IBindingWithOrOnSyntax<T> WithConstructorArgument(string name, Func<Ninject.Activation.IContext, object> callback);
With this overload the callback is called every time an object is created. So my code looks like this and the MakeConnectionString method is called every time.
_Kernel = new StandardKernel();
_Kernel.Bind<ISomeItemRepository>().To<FakeSomeItemRepository>()
.WithConstructorArgument("connectionString", (c) =>
{
MakeConnectionString();
});
In a controller, I do the following:
DBContext DB = new DBContext();
var u = DB.Users.Find(1);
u.firstname = "blah";
UpdateModel(u);
DB.SaveChanges();
I want to do the same from within a model...
namespace Project.Models
{
public class User
{
public void resetPassword()
{
// Generate new password, etc.
this.password = "blah";
}
}
}
Any idea how I go about doing this? It seems UpdateModel() is only available from within controllers.
I'm using EntityFramework Code-First CTP5.
I think UpTheCreek is correct but it probably needs some explanation so I'll try to expand on his/her answer. The first step would be to use the repository pattern. You can find many examples of this pattern in MVC with a google search - this is a particularly gentle introduction (about 3/4's down the page).
The walkthrough goes on to mention dependency injection, and that's something that's also worth looking in to. I tend to favor Ninject myself, however there are other dependency injection containers available.
Putting data access concerns in your model is not a good idea.
Update: Yes, you'd usually have a data access layer for this. As Andy says, the currently fashionable way to do this is using a repository. As a rule, you don't want anything in your model that is not core business logic.
We are currently developing an application based on NHibernate and ASP.NET MVC and a SQL Server backend. Since I'm fairly new to NHibernate, I'm tryig to understand best practices.
Our application requires every user to have it's own SQL Server database. These databases all have an identical structure.
Our customers are identified with a customercode, e.g. 1500.
We've come up with a custom connection provider for nHibernate, which we already use in our nServiceBus backend services:
public class DynamicConnectionProvider : DriverConnectionProvider
{
public override IDbConnection GetConnection()
{
IDbConnection conn = Driver.CreateConnection();
try
{
var messageExecutionContext = ServiceLocator.Current.GetInstance<ITTTContextProvider>().CurrentContext;
if (messageExecutionContext.CustomerId == 0)
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["dev"]
.ConnectionString;
}
else
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["default"]
.ConnectionString
.FormatWith(messageExecutionContext.CustomerId);
}
conn.Open();
}
catch (Exception)
{
conn.Dispose();
throw;
}
return conn;
}
}
This connection provider checks the customer code in a context object and sets the connectionstring accordingly.
We are planning to provide a HttpContext aware ITTTContextProvider. For this I have two questions:
How can we retrieve the customer code from the url and put it into our context object for every request? when we use the following route?
<main-site-url>/{customercode}/{controller}/{action}/{id}
Is this method of connecting to several identical databases valid or is it better practice to construct a sessionfactory foreach customer database?
In order to get the customercode you need to access the route data, something along the lines of
HttpContextBase currentContext = new HttpContextWrapper(HttpContext.Current); //ServiceLocator.Current.GetInstance<ITTTContextProvider>().CurrentContext;
RouteData routeData = RouteTable.Routes.GetRouteData(currentContext);
var cusomterCode = routeData.Values["customercode"]
My second suggestion would be not to put this code in the above snippet provided. Abstract it away. See Joshua's answer which highlights the approach I am thinking of.
Can't really help on the second question, actually not familiar with both frameworks mentioned.
See my recent blog post which shows how to use a subdomain to connect to different databases, although it would be easy to implement your own version of ITenantContext that grabbed the customer code from the request url. Also uses separate session factories for each tenant.
http://www.yellowfeather.co.uk/2011/01/multi-tenancy-on-sharp-architecture/
I am currently playing around with the HybridSessionBuilder class found on Jeffrey Palermo's blog post:
http://jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple/
Using this class, my repository looks like this:
public class UserRepository : IUserRepository
{
private readonly ISessionBuilder _sessionBuilder;
public UserRepository(ISessionBuilder sessionBuilder)
{
_sessionBuilder = sessionBuilder;
}
public User GetByID(string userID)
{
using (ISession session = _sessionBuilder.GetSession())
{
return session.Get<User>(userID);
}
}
}
Is this the best way to go about managing the NHibernate session / factory? I've heard things about Unit of Work and creating a session per web request and flushing it at the end. From what I can tell, my current implementation isn't doing any of this. It is basically relying on the Repository to grab the session from the session factory and use it to run the queries.
Are there any pitfalls to doing database access this way?
You should not wrap your ISession in a using statement -- the point of passing the ISessionBuilder into the repository constructor (dependency injection) is that the calling code is responsible for controlling the life cycle of the ISession. By wrapping it in a using, Dispose() is called on the ISession and you won't be able to lazy load object members or persist it.
We do something similar by just passing in an ISession to the repository constructor. Mr. Palermo's code, as I understand it, simply adds lazy initialization of the ISession. I don't think that's needed because why would you new up a repository if you're not going to use it?
With ASP.Net MVC you want to make sure the life of the session is maintained during the Action method on your controller, as once your controller has exited all your data should be collected. I am not sure if this mechanism will help with that.
You might want to look into S#arp Architechure which is a set of libraries and guidance for building ASP.Net MVC application using nHibernate. http://code.google.com/p/sharp-architecture/
This is the setup I used after researching this more. Seems to work great and doesn't have that annoying habit of creating an ISession on static file requests like most guides out there:
http://www.kevinwilliampang.com/2010/04/06/setting-up-asp-net-mvc-with-fluent-nhibernate-and-structuremap/
I wouldn't open and close sessions on each data request to NHibernate. I would use the Unit of Work libraries that many others suggest or do some more reading. NHForge.org is getting started and I believe that there are some practices on setting up NHibernate for a general web application.
One of the "oh wow that's cool moments" that I've gotten from NHibernate was taking advantage of lazily loading collections during development. It was a neat experience being able to not have to do all those joins in order to display data on some associated object.
By closing the session like this, the above scenario would not be possible.
There might be something that is going on with transactions as well.
Just found a clean solution using Unity to inject a session per request:
http://letsfollowtheyellowbrickroad.blogspot.com/2010/05/nhibernate-sessions-in-aspnet-mvc.html