Seeding EF Database in a Separate DAL Project - asp.net

I'm starting a new ASP.NET project, and I'm trying to follow the multi-project approach I've seen mentioned in multiple questions around Stackoverflow.
I've been following this tutorial, but it assumes only one project for your entire solution. Most notably, it recommends modifying your Global.asax file with code to set the database initializer.
Seeing as how my DAL project doesn't have a Global.asax file, what is the correct procedure for seeding the initial EF database?

I stand corrected in my above comment that you would have access to the DAL by secondary reference. If you are truly wanting to keep from referencing the DAL in your web project, create a Bootstrapper class in your BLL that does the database stuff for you
The examples are pulled from the following blog post: http://weblogs.asp.net/rashid/archive/2009/02/17/use-bootstrapper-in-your-asp-net-mvc-application-and-reduce-code-smell.aspx
Create a bootstrap interface
public interface IBootstrapperTask
{
void Execute();
}
Create a class that would handle your database configuration
public class InitializeDatabase : IBootstrapperTask
{
public void Execute()
{
Database.SetInitializer(new Configuration());
using (var db = new Context())
{
try
{
db.Database.Initialize(false);
}
catch (DataException ex)
{
}
catch (Exception ex)
{
throw;
}
}
}
}
Create a static class that will execute the tasks (you can have more than one, registering routes could be moved to a BootstrapperTask)
public static class Bootstrapper
{
static Bootstrapper()
{
ConfigureContainer();
}
public static void Run()
{
var tasks = ServiceLocator.Current.GetAllInstances<IBootstrapperTask>();
foreach(var task in tasks)
{
task.Execute();
}
}
private static void ConfigureContainer()
{
IUnityContainer container = new UnityContainer();
UnityConfigurationSection configuration = (UnityConfigurationSection) ConfigurationManager.GetSection("unity");
configuration.Containers.Default.Configure(container);
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
}
}
Finally, your global.asax would have a one liner
protected void Application_Start()
{
Bootstrapper.Run();
}
There are some web.config things to do as well that you will see in the blog posting. Also, this question can lend some more information on the specifics of disposing, etc. There are more benefits to boostrapping than simply not having to reference a DAL with some excellent posts around the community on why using this pattern is a good thing as well as a few different approaches on implementation.

In the Application_Start of the Global.asax:
Database.SetInitializer(new Configuration());
using (var db = new Context())
{
try
{
db.Database.Initialize(false);
}
catch (DataException ex)
{
}
catch (Exception ex)
{
throw;
}
}
Where the Context class lives in the DAL:
public class Context : DbContext
{
public Context() : base("YourDatabaseName") { }
public DbSet<Employee> Employees { get; set; }
// ...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new EmployeeMap());
You do the mapping in a dedicated class public class EmployeeMap : EntityTypeConfiguration<Employee>.
Seeding is done in the DAL:
public sealed class Configuration : DropCreateDatabaseAlways<Context>
{
protected override void Seed(Context context)
{
// Do your seeding here
}
}

Related

Internal Server Error 500 Asp.net WebApi trying to DI with Entity

I am building an ASP.net WebApi, and trying to use Entity alongside. I am following this guide.
Getting Started with ASP.NET Web API 2 (C#)
I am receiving a 500 internal server error using Fiddler. The JSON Exception message states ExceptionMessage=An error occurred when trying to create a controller of type 'LocationsController'. Make sure that the controller has a parameterless public constructor.
Here is the Controller.cs
[RoutePrefix("api/Locations")]
public class LocationsController : ApiController
{
// GET api/<controller>
private IlocationsRepository LocationsRepo;
public LocationsController(IlocationsRepository _repo)
{
if (_repo == null) { throw new ArgumentNullException("_repo"); }
LocationsRepo = _repo;
}
[HttpGet]
[Route("")]
public IEnumerable<Location> GetAll()
{
return LocationsRepo.GetAll();
}
}
I can't use a parameterless public constructor because I need to use the Database Repository that was created for Locations. I verified the issue was with the IlocationsRepository by doing the following.
When I replace the LocationsController constructor with no parameters , and declare a List<Location> within the controller, and use dummy data. I receive a 200 with all the json data correct.
Here is the start of the Global.asax.cs file
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
protected void Session_Start(object sender, EventArgs e)
{
}
}
It seems as if I need to do the dependency injection in the Global, but none of the guides had any information regarding this part.
For posterity here is the ContextDB cs
public class WebServerContext : DbContext
{
public WebServerContext() : base("WebServerContext") {}
public DbSet<Order> dOrders { get; set; }
public DbSet<Location> dLocations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
For additional posterity, here is the Locations Repository.
public class LocationsRepository : IlocationsRepository
{
private z_Data.WebServerContext db = new z_Data.WebServerContext();
public void Add(Location item)
{
db.dLocations.Add(item);
}
public IEnumerable<Location> GetAll()
{
return db.dLocations;
}
}
As per Dependency Injection for Web Api tutorial on MSDN, you are missing the line to register the dependency resolver (a concrete class that implements System.Web.Http.IDependencyResolver) with Web Api. It acts like a bridge between your DI container and Web Api so it can resolve your constructor dependencies.
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
container.RegisterType<IProductRepository, ProductRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container); // <- You need this
// Other Web API configuration not shown.
}
Of course, that assumes you are using Unity. If not, you should either use the DependencyResolver that came with your DI container or implement your own.
NOTE: With some DI containers, you also need to register all of your controllers explicitly.

Unity.Webforms dbcontext per request

I am implementing dependency injection using Unity and the Unity.Webforms bootstrapper. I have a DbFactory in my webforms application which initializes my DbContext, and I am wanting to create one instance of this factory per web request, so that my various services will update under the same unit of work.
My question is, does the Unity.Webforms bootstrapper take care of this for me? I believe the answer in this post is suggesting doing the following in order accomplish a single context per request.
container.RegisterType<IDbFactory,DbFactory>(new HierarchicalLifetimeManager());
Is this correct, and is it all I need to do? I'm worried that it is creating a single context per request, but that it is an application wide context (all users sharing the same context).
This probably isn't necessary, but just in case, here is the implementation code for my DbFactory.
public class DbFactory : Disposable, IDbFactory
{
MyDbContext dbContext;
public MyDbContext Init()
{
return dbContext ?? (dbContext = new MyDbContext());
}
protected override void DisposeCore()
{
if(dbContext != null)
{
dbContext.Dispose();
}
}
}
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
protected virtual void DisposeCore(){}
}

Unity injection into asp.net web api controllers and filters

I have WebForms project, and there I have WebApi controller.
How I can inject to controller constructor and to action filter constructor?
I have implemented IDependencyResolver and use it in Global.asax (GlobalConfiguration.Configuration.DependencyResolver), but it doesn't help:
on request controller says that there is no default constructor and filter on application start says that it does not contain a constructor that takes 0 arguments.
Moreover, i need singletone injection to action filter.
Thanks.
UPD
public class ScopeContainer : IDependencyScope
{
protected readonly IUnityContainer _container;
public ScopeContainer(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.IsRegistered(serviceType) ? _container.ResolveAll(serviceType) : new List<object>();
}
public void Dispose()
{
_container.Dispose();
}
}
public class IoCContainer : ScopeContainer, IDependencyResolver
{
public IoCContainer(IUnityContainer container) : base(container)
{
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new ScopeContainer(child);
}
}
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterInstance<ILogger>(new Logger());
unity.RegisterType<IRepository, DbRepository>();
config.DependencyResolver = new IoCContainer(unity);
}
private static void RegisterRoutes()
{
RouteTable.Routes.MapHttpRoute("ServiceApi", "api/{controller}/{action}");
}
}
I think this may be the way you are registering your routes.
WebApi routes are registered in the default project examples via the GlobalConfiguration.Routes rather than the RouteTable.Routes which is used by MVC controllers. If the ApiController is being incorrectly loaded by the MVC routing method it won't find your dependency resolver.
Try modifying your code to this:
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(GlobalConfiguration.Configuration);
ConfigureApi(GlobalConfiguration.Configuration);
}
void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterInstance<ILogger>(new Logger());
unity.RegisterType<IRepository, DbRepository>();
config.DependencyResolver = new IoCContainer(unity);
}
private static void RegisterRoutes(HttpConfiguration config)
{
config.Routes.MapHttpRoute("ServiceApi", "api/{controller}/{action}");
}
}
I was having the same issue, I was working on a project trying to help modernize an old web forms project by converting page by page to Web API / Angular and getting the plumbing just right to use Unity was key.
When I was tracing I noticed unity was trying to resolve the controller classes but not the types to inject into their constructors, so I registered my controllers and it all worked. See my example below
Config setup, register controller and dependency
void ConfigureApi(HttpConfiguration config)
{
var container = UnitySingleton.UnityContainer;
container.RegisterType<IDashboardManager, ExampleStuff>();
container.RegisterType<DashboardController>(new InjectionConstructor(container.Resolve<IDashboardManager>()));
config.DependencyResolver = new UnityIoCContainer(container);
}
And my controller example:
public class DashboardController : ApiController
{
private readonly IDashboardManager _dashboardManager;
public DashboardController(IDashboardManager dashboardManager)
{
_dashboardManager = dashboardManager;
}
public async Task<IEnumerable<string>> Get()
{
return await _dashboardManager.GetDatas();
}
}
This is how I got mine working. It was a little different than the article above.

What are best practices for managing DataContext?

In an effort to make my entities persistent ignorant and make my repositories testable, I've implemented a repository pattern like so:
public interface IJobRepository : IRepository<Job>
{
Job GetJobById(int jobId); //Special case where I'm eager loading other entities
void SaveJob(Job job, Job originalJob);
}
public class JobRepository : IJobRepository
{
private readonly IContext _context;
public JobRepository()
{
_context = new CustomObjectContext();
}
public JobRepository(UnitOfWork unitOfWork)
{
_context = unitOfWork.Context;
}
//Basic GetAll, GetById, Add and Delete methods from IRepository<T> Interface here
//omitted for brevity
public Job GetJobById(int jobId)
{
var job = _context.Jobs.Include("Company").Include("Location").
Include("PlantInfo").Where(j => j.Jobid == jobId).SingleOrDefault();
_context.DisposeContext();
return job;
}
public void SaveJob(Job job, Job originalJob)
{
if (job.Jobid > 0)
{
// Update
_context.Jobs.Attach(originalJob);
_context.PlantInfoes.Attach(originalJob.PlantInfo);
_context.Jobs.ApplyCurrentValues(job);
_context.PlantInfoes.ApplyCurrentValues(job.PlantInfo);
Note: ApplyCurrentValues is an extension method I'm using on the ObjectSet
}
else
{
// Create
_context.Jobs.AddObject(job);
}
_context.Save();
}
}
public class UnitOfWork
{
private readonly IContext _context;
public UnitOfWork()
{
_context = new CustomObjectContext();
}
public UnitOfWork(IContext context)
{
_context = context;
}
public string Save()
{
return _context.Save();
}
internal IContext Context
{
get { return _context; }
}
}
public interface IContext
{
IObjectSet<Job> Jobs { get; }
IObjectSet<Company> Companies { get; }
IObjectSet<Location> Locations { get; }
IObjectSet<PlantInfo> PlantInfoes { get; }
string Save();
}
My ObjectContext inherits from IContext...So my understanding is that I will only use the overloaded constructor on the repository to facilitate unit tests or to use it in the case that I want to use the same context (not desirable based on this post I found on SO "Entity Framework and Connection Pooling" -- Is this right?
Also, assuming the context only gets disposed when the repository is garbage collected, I have to dispose the context explicitly to avoid the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." exception when attaching the entity prior to a save.
That said, what is the best practice for managing the DataContext in a manner that keeps your entities persistent ignorant and repositories testable?
Note: This is an asp.net webapplication; UnitOfWork and IContext implementation was based on examples from "Programming Entity Framework", Second Edition by Julia Lerman Ch24.
Thanks in advance!
Firstly, I would ensure that whatever my "consumable" object is (either repository or unit of work, depending on your setup) implements IDisposable. When your consumbed object is disposed of, then you would dispose your underlying context.
For instance, if you're using your UnitOfWork as the consumable object (the one that gets created and called in your application), it would look something like:
public class UnitOfWork : IDisposable
{
// All the other stuff you had before plus:
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
}
(Note: This can also be done on your repositories if they're the ones being consumed directly)
And then, you have a few options in your application. If you are going to use the UnitOfWork directly, you can use it like:
public void SomeMethodThatAccessesYourData ()
{
using (var unitOfWork = new UnitOfWork (/*Load in the context*/))
{
// Access your data here.
}
}
Or, in your Web Forms or MVC object you can use constructor injection and dispose of it when the Web Forms or MVC object is disposed of:
// If you're using MVC:
public class MyController : Controller
{
private UnitOfWork _unitOfWork;
public MyController (UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public override Dispose (bool Disposing)
{
if (Disposing && _unitOfWork != null)
{
_unitOfWork.Dispose ();
}
}
}
The same idea stands for a web forms Page.
The main reason for using the constructor overload is for Inversion of Control (IOC). It helps with both unit testing and with production code when used with an IoC Container. WebForms doesn't lend itself well to IoC, but it is really easy with MVC.
Edit
I don't really see the connection with your repositories and the unit of work. Usually you access the repositories from a unit of work or, in other implementations, you request a unit of work from your target repository. In your implementation (which I understand is not your own) there seems to be no need for both.
Edit 2
If the UoW is overkill for your application, and you know you can use IoC to inject your IContext, and you don't have very many repositories, you can do something like:
public IRepository<T> : IDisposable { }
public IJobRepository : IRepository<Job> { /* All the stuff you put here */ }
public JobRepository : IJobRepository
{
private IContext _context;
...
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
public JobRepository (IContext context)
{
_context = context;
}
}
Then, how you use it depends on your specific task. I'm not a fan of this direct use of IRepository, but this answer is getting too long.

NullReferenceExpection in a Integration test project for an asp.net nhibernate solution

i have a .NET 3.5 solution with an asp.net(web site) project with fluentnhibernate and it's test project(class library project).i've referenced the asp.net project in the test project and with all fluentnhibernate/nhibenate dlls.
What i fail to comprehend is that, on a run of a webform (hit from browser) let's say Test.aspx, building of schema is successfull and i could see the tables in my database.
here is the method i call on Test.aspx.cs
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ISession session = SessionManager.Instance.OpenSession();
SessionManager.BuildSchema(session);
}
}
i happen to use the same method in CanGenerateSchema method of my test class and it always fails
[TestFixture]
public class CanGenerateSchemaTestSuite
{
[Test]
public void CanGenarateSchema()
{
ISession session = SessionManager.Instance.OpenSession();
SessionManager.BuildSchema(session);
}
}
here is the SessionManager i use :
public sealed class SessionManager
{
private readonly ISessionFactory _sessionFactory;
public static ISessionFactory SessionFactory
{
get { return Instance._sessionFactory; }
}
private ISessionFactory GetSessionFactory()
{
return _sessionFactory;
}
public static SessionManager Instance
{
get { return NestedSessionManager._sessionManager; }
}
public ISession OpenSession()
{
return Instance.GetSessionFactory().OpenSession();
}
private static Configuration SaveConfigs;
private SessionManager()
{
try
{
if (_sessionFactory == null)
{
//from the debugging the code breaks from here when trying to get connectionstring.
string constring = ConfigurationManager.AppSettings["localdb"].ToString();
FluentConfiguration configuration = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(constring))
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<myproject.model.Request>();
m.FluentMappings.AddFromAssemblyOf<myproject.model.Route>();
})
.ExposeConfiguration((x) =>
{
SaveConfigs = x;
x.SetProperty("current_session_context_class", "thread_static");
});
_sessionFactory = configuration.BuildSessionFactory();
}
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
}
public static void BuildSchema(ISession session)
{
var export = new SchemaExport(SaveConfigs);
export.Execute(false,true,false,session.Connection,null);
}
class NestedSessionManager
{
internal static readonly SessionManager _sessionManager = new SessionManager();
}
}
So from my comment the NullReferenceException happens when accessing the connectionstring. I don't have the explanation on why that happens.I'm sure it's some kind of gotchas, i can't get over it.I would be very grateful if anyone could give me a hand here.thanks for reading.
ConfigurationManager.AppSettings["localdb"] from Test.aspx would be pulling from your web.config file on a web project.
That file wouldn't be accessible to your test project (I'm assuming your tests are in a separate project from your web site). You should be able to get around this by adding an app.config file into your test project with the correct localdb settings or rather than using a configuration string, use FluentNHibernate's fluent builder.
Example app.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="localdb" value="yourconnectionstring" />
</appSettings>
</configuration>
If the value returned by ConfigurationManager.AppSettings["localdb"] is null then the .ToString() call will cause the NullReferenceException.
Ensure the "localdb" setting exists.

Resources