I am struggling with using multiple dbContext with an single web application in ASP.NET MVC 5. I am following code First existing database design approach.
so i have created dashboardModel using ADO.NET Entity model, that comes with its own dbContext (DashboardContext) and then roleModel using again ADO.net Entity Model (dbContext = RoleContext).
I want to keep similar concern of model separtate and their individual DBContext.
On creating DashboardModel, code run without problem but when i have created RoleModel and run; it gives me error on Dashboard controller ==> MetadataException was unhandled by user code
public DashboardContext()
: base("name=DashboardContext")
{
}
////
public class DashboardController : Controller
{
//
// GET: /Dashboard/
public ActionResult Home()
{
using (var db = new DashboardContext())
{
var query = from b in db.sys_Functions
orderby b.Function_ID
select b;
foreach(var item in query)
{
var a1 = item.Title;
}
}
return View();
}
}
//
public RoleContext()
: base("name=RoleContext")
{
}
//
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Index()
{
using(var db = new RoleContext())
{
var query = from x in db.AspNetRoles
orderby x.Name
select x;
foreach(var item in query)
{
var t = item.Name;
}
}
return View();
}
}
Many Thanks
I want to keep similar concern of model separtate and their individual DBContext.
DbContext is the abstraction for a database. So unless you are connecting your entities to different databases, there's no reason to use different Db contexts.
Note: this may not be so related to the question
I wanted to make two ApplicationDbContext with two different connections in ASP.NET MVC 5 (not ASP.NET CORE)
This is what worked for me, first you will need to add a second / overloaded constructor to ApplicationDbContext
Then add another ApplicationDbContext class like "ReadOnly_1_Local_ApplicationDbContext" that inherits the orignial ApplicationDbContext not the "IdentityDbContext" and make its constructor calls the overloaded base constructor with your new connection
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("<your connection>", throwIfV1Schema: false)
{
}
public ApplicationDbContext(string nameOrConnectionString) : base(nameOrConnectionString, throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public class ReadOnly_1_Local_ApplicationDbContext : ApplicationDbContext
{
public ReadOnly_1_Local_ApplicationDbContext() : base("<your read only connection>")
{
}
}
Usage (I stopped sync from the first db to the read only one and changed the data in one of them to see it really connects to the other db)
public ActionResult TestMultiDbContext_1()
{
var db_context = new ApplicationDbContext();
return Content(db_context.Shipments.Find(123456).CustomerName); // name #1
}
public ActionResult TestMultiDbContext_2()
{
var db_context = new ReadOnly_1_Local_ApplicationDbContext();
return Content(db_context.Shipments.Find(123456).CustomerName); //name #2
}
That is tested with code first migrations and does not cause any issue and is not generating any extra migrations.
If you are adding another connection for entirely new db (not duplicated one), just make another class that inherits the IdentityDbContext normally
Thanks
Related
We have ASP MVC web project. After reading a lot of articles and discussions here in stackoverflow about the correct architechture we have decided to go with the following one, although there is not only one correct way of doing things this is the way we have decided, but we still have some doubts.
We are publishing this here not only to be helped but also to show what we have done in case it is helpful to somebody.
We are working in ASP .NET MVC project, EF6 Code first with MS SQL Server.
We have divided the project into 3 main layers that we have separate into 3 projects: model, service and web.
The model creates the entities and setup the DataContext for the database.
The service make the queries to the data base and transform those entities into DTOs to pass them to the web layer, so the web layer doesn't know anything about the database.
The web uses AutoFac for the DI (dependency Injection) to call the services we have in the service layer and obtain the DTOs to transform those DTOs into Model Views to use them in the Views.
After reading a lot of articles we decided not to implement a repository pattern and unit of work because, in summary, we have read the EF acts as a unit of work itself. So we are simplifying things a little here.
https://cockneycoder.wordpress.com/2013/04/07/why-entity-framework-renders-the-repository-pattern-obsolete/
This is the summary of our project. Now I'm going to go through every project to show the code. We are going to show only a couple of entities, but our project has more than 100 different entities.
MODEL
Data Context
public interface IMyContext
{
IDbSet<Language> Links { get; set; }
IDbSet<Resources> News { get; set; }
...
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
}
public class MyDataContext : DbContext, IMyContext
{
public MyDataContext() : base("connectionStringName")
{
}
public IDbSet<Language> Links { get; set; }
public IDbSet<Resources> News { get; set; }
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}
}
Here is how we declare the entities
public class Link
{
public int Id{ get; set; }
public string Title { get; set; }
public string Url { get; set; }
public bool Active { get; set; }
}
SERVICES
These are the generic classes we use for all the services.
As you see we use the DTOs to get data from the web layer. Also we connect to the database using Dbset = Context.Set()
public interface IService
{
}
public interface IEntityService<TDto> : IService where TDto : class
{
IEnumerable<TDto> GetAll();
void Create(TDto entity);
void Update(TDto entity);
void Delete(TDto entity);
void Add(TDto entity);
void Entry(TDto existingEntity, object updatedEntity);
void Save();
}
public abstract class EntityService<T, TDto> : IEntityService<TDto> where T : class where TDto : class
{
protected IClientContext Context;
protected IDbSet<T> Dbset;
protected EntityService(IClientContext context) { Context = context; Dbset = Context.Set<T>(); }
public virtual IEnumerable<TDto> GetAll()
{
return Mapper.Map<IEnumerable<TDto>>(Dbset.AsEnumerable());
}
public virtual void Create(TDto entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
Dbset.Add(Mapper.Map<T>(entity));
Context.SaveChanges();
}
public virtual void Update(TDto entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
Context.Entry(entity).State = EntityState.Modified;
Context.SaveChanges();
}
public virtual void Delete(TDto entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
Dbset.Remove(Mapper.Map<T>(entity));
Context.SaveChanges();
}
public virtual void Add(TDto entity)
{
Dbset.Add(Mapper.Map<T>(entity));
}
public virtual void Entry(TDto existingEntity, object updatedEntity)
{
Context.Entry(existingEntity).CurrentValues.SetValues(updatedEntity);
}
public virtual void Save()
{
Context.SaveChanges();
}
}
We declare the DTOs in this project (this is a very simple example so we don't have to put all the code here):
public class LinkDto
{
public int Id { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public bool Active { get; set; }
}
Then one of our services:
public interface ILinkService : IEntityService<LinkDto>
{
IPagedList<LinkDto> GetAllLinks(string searchTitle = "", bool searchActive = false, int pageNumber = 1, int pageSize = 10);
LinkDto FindById(int id);
LinkDto Test();
}
public class LinkService : EntityService<Link, LinkDto>, ILinkService
{
public LinkService(IClientContext context) : base(context) { Dbset = context.Set<Link>(); }
public virtual IPagedList<LinkDto> GetAllLinks(bool searchActive = false, int pageNumber = 1, int pageSize = 10)
{
var links = Dbset.Where(p => p.Active).ToPagedList(pageNumber, pageSize);
return links.ToMappedPagedList<Link, LinkDto>();
}
public virtual LinkDto FindById(int id)
{
var link = Dbset.FirstOrDefault(p => p.Id == id);
return Mapper.Map<LinkDto>(link);
}
public LinkDto Test()
{
var list = (from l in Context.Links
from o in Context.Other.Where(p => p.LinkId == l.Id)
select new OtherDto
{ l.Id, l.Title, l.Url, o.Other1... }).ToList();
return list;
}
}
As you see we use AutoMapper (version 5 which has changed a little) to transform from Entities to DTOs the data.
One of the doubts we have is if the use of "Dbset.Find" or "Dbset.FirstOrDefault" is correct and also if the use of "Context.Links" (for any entity).
WEB
FInally the web project where we receive the DTOs and transform those DTOs into ModelViews to show in our views.
We need to call, in the Global.asax Application_Start, AutoFac to do the DI so we can use our services.
protected void Application_Start()
{
...
Dependencies.RegisterDependencies();
AutoMapperBootstrapper.Configuration();
...
}
public class Dependencies
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
builder.RegisterModule(new ServiceModule());
builder.RegisterModule(new EfModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
public class ServiceModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(Assembly.Load("MyProject.Service")).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerLifetimeScope();
}
}
public class EfModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType(typeof(MyDataContext)).As(typeof(IMyContext)).InstancePerLifetimeScope();
}
}
As you see we also call AutoMapper to configure the different maps.
Then in our controllers we have this.
public class LinksController : Controller
{
private readonly ILinkService _linkService;
public LinksController(ILinkService linkService)
{
_linkService = linkService;
}
public ActionResult Index()
{
var links = _linkService.GetAllLinks();
return View(links.ToMappedPagedList<LinkDto, LinksListModelAdmin>());
}
...
public ActionResult Create(LinksEditModelAdmin insertedModel)
{
try
{
if (!ModelState.IsValid) return View("Create", insertedModel);
var insertedEntity = Mapper.Map<LinkDto>(insertedModel);
_linkService.Create(insertedEntity);
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
}
}
}
Well, this is it...I hope this can be useful for somebody...and also I hope we can have a little help with the questions we have.
1) Although we are separating database from the web project we do need a reference in the web project to initialize the database and also to inject dependencies, is this correct?
2) Is it correct the approach we have done having our Entities->DTOs->ViewModels? It's a little more work but we have everything separated.
3) In the Service project, when we need to reference a different entity than the main one we are using in the service, is it correct to call Context.Entity?
For example, if we need to retrieve also data from the News entity in the links service, is it correct to call "Context.News.Where..."?
4) We do have a little problem with Automapper and EF proxy, because when we call "Dbset" to retrieve data, it gets a "Dynamic proxies" object so Automapper can't find the proper map so, in order to work, we have to set ProxyCreationEnabled = false in the DataContext definition. This way we can get an Entity in order to map it to the DTO. This disables LazyLoading, which we don't mind, but is this a correct approach or there is a better way to solve this?
Thanks in advance for your comments.
For Question no. 2
Entities->DTOs->ViewModels? is good approach
because you are doing the clean separation, the programmer can work together with ease.
The person who design ViewModels, Views and Controllers don't have to worry about the service layer or the DTO implementation because he will make the mapping when the others developpers finish their implementation.
For Question no. 4
When the flag ProxyCreationEnabled is set to false, the proxy instance will not be created with creating a new instance of an entity. This might not be a problem but we can create a proxy instance using the Create method of DbSet.
using (var Context = new MydbEntities())
{
var student = Context.StudentMasters.Create();
}
The Create method has an overloaded version that accepts a generic type. This can be used to create an instance of a derived type.
using (var Context = new MydbEntities())
{
var student = Context.StudentMasters.Create<Student>();
}
The Create method just creates the instance of the entity type if the proxy type for the entity would have no value (it is nothing to do with a proxy). The Create method does not add or attach the entity with the context object.
Also i read some where if you set ProxyCreationEnabled = false the child element will not loaded for some parent object unless Include method is called on parent object.
I would like to take a model of a table and make a viewmodel with additions fields, then populate it as a view. How do I do this in the controller? When it was just a model it worked but I'm not sure how to do the same thing when it's a viewmodel. I'm new to asp.net mvc so any help would be appreciated.
Model:
public partial class tblTag
{
public int TagId { get; set; }
public string TagName { get; set; }
}
ViewModel:
public class tblTagViewModel
{
public string TagName { get; set; }
public string TagNameClr
{
get
{
if (TagName == "Test")
{
return "green";
}
else
{
return "red";
}
}
}
}
Controller:
Cannot implicitly convert type 'System.Data.Entity.DbSet<_1MvcSqlServer.Models.tblTag>' to '_1MvcSqlServer.ViewModel.tblTagViewModel'
Now that it's a viewmodel the structure from entities is different, I assume that is the problem. How do I resolve this?
private testEntities db = new testEntities();
public ActionResult Test()
{
ViewModel.tblTagViewModel model = new ViewModel.tblTagViewModel();
model = db.tblTags;
return(model);
}
Here is what I ended up with to get it to work. Is this the correct method?
public ActionResult Test()
{
List<ViewModel.tblTagViewModel> list = new List<ViewModel.tblTagViewModel>();
var model = new ViewModel.tblTagViewModel();
foreach(tblTag p in db.tblTags)
{
ViewModel.tblTagViewModel nw = new ViewModel.tblTagViewModel();
nw.TagName = p.TagName;
list.Add(nw);
}
return View(list);
}
Correct method - create Business layer, which would get data from DB layer and pass this data to View layer (and vice versa, get data from View layer and pass to DB layer).
Also, I recommend to look at IoC (DI) approach :
Business Layer:
First at all, you create new ClassLibrary project and create Business layer POCO classes and an abstraction of your repository:
/// <summary>
/// this is a Business layer class, which is very similar on EF class
/// </summary>
public class Tag
{
public int TagId { get; set; }
public string TagName { get; set; }
}
public interface IRepository
{
List<Tag> GetTagList();
}
Then you create Service:
public class Service
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_repository = repository;
}
public List<Tag> GetTagList()
{
return _repository.GetTagList();
}
}
on this stage you have compiled version of Business layer. You can add all complex logic of your application and test it. Attent, without DB amd View parts!
Next step - create DB layer
DB Layer:
Create one more Class Library in your solution, add link to BL project and add code like this:
public class EFRepository : IRepository
{
private ... _db;
public EFRepository()
{
.....
}
public List<Tag> GetTagList()
{
var tags = (from i in _db.tblTags select new Tag { TagId = i.TagId, TagName = i.TagName }).ToList();
}
}
so, you have DB and BL layers. And your BL layer is not depend on DB layer, vice versa, DB layer is depend on BL layer .And it's a correct approach, business logic of your application should not be depended on DB!
The last step - View Layer.
View Layer
You can separate View Layer to different project too. I do it inside my ASP.NET MVC application. Add references to DB and BL projects
public class tblTagViewModel
{
public string TagName { get; set; }
public string TagNameClr
{
get
{
if (TagName == "Test")
{
return "green";
}
else
{
return "red";
}
}
}
}
and your controller:
public class HomeController : Controller
{
private readonly Service _service;
public HomeController(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_service = new Service(repository);
}
public ActionResult Test()
{
List<ViewModel.tblTagViewModel> list = new List<ViewModel.tblTagViewModel>();
vat taglist = _service.GetTagList();
foreach (tblTag p in taglist)
{
ViewModel.tblTagViewModel nw = new ViewModel.tblTagViewModel();
nw.TagName = p.TagName;
list.Add(nw);
}
return View(list);
}
}
and, the last step, set DB implementation to your web app:
public class MyControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
var efRepository = new EFRepository();
if (controllerType == typeof(HomeController))
{
return new HomeController(efRepository );
}
return base.GetControllerInstance(requestContext, controllerType);
}
pay attention, that your web-application is not depend on DB layer, it depends only on BL layer (this is logical too). Only one place to set EFRepository in your web application - in controller factory.
With this approach you can easily change EFRepository to another implementation of IRepository, with different DB or even fake DB. You can test any part of your application without unnecessary relationships. You have strong and correct architecture, where your application depend on business logic layer and not depend on DB layer etc. Any changes in DB layer or View layer are not affect on logic layer
For mapping similar POCO classes (i.e BL and DB, BL and View classes) with many properties you can user Automapper
I started refactoring an ASP.Net 5 web application which uses MVC 6 and Entity Framework 7 when I was wondering about some points. My controllers currently use the DbContext implementation via dependency injection to fill the view models and return them for rendering with the view. Like:
public class UserController : Controller
{
[FromServices]
public MyContext myContext { get; set; }
//route which renders all users
public IActionResult Index()
{
var users = myContext.User.OrderBy(u => u.Name);
List<UserIndexViewModel> v = new List<UserIndexViewModel>();
foreach (var item in users)
{
v.Add(new UserIndexViewModel { Name = item.Name, City = item.City, DateOfBirth = item.DateOfBirth });
}
return View(v);
}
//route to edit user
public async Task<ActionResult> Edit(int id)
{
User user = await FindUserAsync(id);
UserEditViewModel v = new UserEditViewModel { Name = user.Name, City = user.City };
return View(v);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Update(int id, UserEditViewModel userModel)
{
User user = await FindUserAsync(id);
try
{
user.Name = userModel.Name;
user.City = userModel.City;
myContext.User.Attach(user);
myContext.Entry(user).State = EntityState.Modified;
await myContext.SaveChangesAsync();
return RedirectToAction("Index");
}
catch (Exception)
{
ModelState.AddModelError(string.Empty, "Unable to save changes.");
}
return View(userModel);
}
private Task<User> FindUserAsync(int id)
{
return myContext.User.SingleOrDefaultAsync(u => u.UserId == id);
}
}
I did some research and I found some blog posts (like this) which asks to keep controllers clean. Ok.. why not?
I started creating a kind of view model builder to put the logic out of the controller methods over to the view model builder. In the above linked article is a hint to create for each view model a own view-model-builder class - which makes sense in my eyes.
For the model User exist two views and thus two view models (UserIndexViewModel and UserEditViewModel). When I create the related view-model-builder classes they should derivate from the same (abstract) class because it could be that both child classes needs a helper method (like FindUserAsync() - it is not the case in my example but just imagine). So I would have a construct like the following:
public interface IViewModelBuilder<TController, TViewModel>
{
TViewModel Build(TController controller, TViewModel viewModel);
Task<TViewModel > BuildAsync(TController controller, TViewModel viewModel);
}
public abstract class UserViewModelBuilder<TViewModel> : IViewModelBuilder<UserController, TViewModel> { ... }
public class UserIndexViewModelBuilder : SiteViewModelBuilder<UserIndexViewModel> { ... }
public class UserEditViewModelBuilder : SiteViewModelBuilder<UserEditViewModel> { ... }
This mentioned function which is needed by multiple view model builders of one model should be implemented in the abstract class (UserViewModelBuilder in my case), right?
I did it like this:
public abstract class UserViewModelBuilder<TViewModel> : IViewModelBuilder<UserController, TViewModel>
{
[FromServices]
public MyContext myContext { get; set; }
public abstract TViewModel Build(UserController controller, TViewModel viewModel);
public abstract Task<TViewModel> BuildAsync(UserController controller, TViewModel viewModel);
public Task<User> FindUserAsync(int id)
{
return myContext.User.SingleOrDefaultAsync(u => u.UserId == id);
}
}
So with this abstract class I can create the implementation of UserIndexViewModelBuilder and UserEditViewModelBuilder classes as well as for example UserDeleteViewModelBuilder and UserCreateViewModelBuilder classes in future...
Now the question:
Is this a right approach to separate the logic from the controller? If yes, do I need a kind of factory for all view model builders which can be accessed via DI in all my controllers? If it is the way which is kind of best practice for MVC applications. Is there something different to the mentioned guide which can/should be used in MVC 6 apps?
Is the abstract class the right place to call the DbContext implementation via DI? It feels not good for me.
Some other points which I missed? Some if-statements for checking response were removed from the UserController snipped for better readability.
Thank you! :-)
Hi I have model class which is written in MVC.I am using Ef database first approach. In model class I have some queries which deals with database. I have following questions :
1) Is it right way to use database related queries in Model and call that in controller or view?
2)If yes where I should call this model? In Controller or in view ??
3)How I should call this model? Say for example I have class called class1.cs in model.How I should call this model?
Your model contains classes that define the different objects troughout your project. This includes properties with their basic information and methods to perform actions on this object.
1)
Do you really need queries? Why not use the Entity Framework to do it for you? Create the mapping for your domain classes (either trough annotations or fluent api) and use the DbContext to retrieve and save the data stored in your database
2)
Ideally people create repositories that are injected into your controllers (Dependency Injection). These repositories can for example contain something like GetPersonById(int id). Inside this method there would be two things:
Perform an action on the domain object
Save it to the DbContext
For example:
public void Subscribe(int userID, Show show) {
var user = GetUserByID(userID);
if (!user.IsSubscribedTo(show.ShowID)) {
user.Subscribe(show);
_dbContext.SaveChanges();
}
}
Controller -> Method call in repository -> Perform action on corresponding domain object -> Save changes to the database
If you need something that doesn't require an object mutation, it's even more simple:
public User GetUserByID(int id) {
return _dbContext.Users.FirstOrDefault(x => x.ID == id);
}
3)
Trough repositories (see above). Your DbContext will have a bunch of DbSets that contain objects that correspond with every data entry in your database. Trough repositories you can work with these objects and manipulate them. When you call the DbContext.SaveChanges() method, it will look at what has changed in these lists and commit the changes to your database.
Repository example:
class User {
public int ID { get; set; }
public string Name { get; set; }
}
class DatabaseContext : DbContext {
public DbSet<User> Users { get; set; }
}
public interface IUserRepository {
User GetUserByID (int id);
bool UsernameExists (string name);
}
public class UserRepository : IUserRepository {
private DatabaseContext _db;
public UserRepository(DatabaseContext db){
_db = db;
}
public User GetUserByID(int id) {
return _db.Users.FirstOrDefault(x => x.ID == id);
}
public User GetUserByUsername(string username) {
return _db.Users.FirstOrDefault(x => x.Name == username);
}
}
public class UserController : Controller {
private IUserRepository _userRepository;
public UserController(IUserRepository userRepository) {
_userRepository = userRepository;
}
public ActionResult Details(int id){
return View(_userRepository.GetUserByID(id);
}
}
// Ninject settings (install this extension, you want it):
private void AddBindings(){
kernel.Bind<DatabaseContext>().ToSelf().InSingletonScope();
kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
}
You could use some sort of Unit Of Work pattern which you inject in your controller constructor using an inversion of control container (IOC), for instance autofac.
Your unit of work class could hold a reference to repositories, where you would query/insert your data.
Roughly;
public class BackendController : Controller
{
private UnitOfWork _worker;
public BackendController(UnitOfWork worker)
{
this._worker = worker;
}
public ActionResult Admin()
{
var items = _worker.MyRepository.GetAll();
return View(items);
}
}
public class UnitOfWork
{
private ContentRepository _contentRepository;
public UnitOfWork()
{
}
public ContentRepository MyRepository
{
get
{
if (_contentRepository != null)
return _contentRepository;
else
return _contentRepository = new ContentRepository();
}
}
}
public class ContentRepository
{
// holds an object context and methods to retrieve and put data (EF or similar)
}
You would have to register your instance with the IOC container in global.asax, application_start for example, something like this (Using autofac as IOC):
UnitOfWork worker = new UnitOfWork();
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterInstance(worker).SingleInstance();
var container = builder.Build();
...
1) Is it right way to use database related queries in Model and call that in controller or view?
I would recommend not directly accessing the database in your model classes, as you have to remember that MVC is strictly a presentation layer pattern. If you do put your database access logic in your model classes, then you will not be able to have any other client use this functionality, such as a web service. Instead have logic that translates your business objects, defined outside of your ASP.NET MVC project, into your ASP.NET MVC model classes.
This is where the power of n-tier architecture shines, if you create a business and data-access layer, then I could write an ASP.NET MVC front-end, WebForms front-end, WPF front-end, WinForms front-end and all of them could access data using the same service. By putting the logic into the ASP.NET MVC model classes, then you are effectively forcing any other client to duplicate that logic again in their classes.
I'm new to Mvc.
Sorry to my english. ^^
I have some question about asp.net MVC session in the controller.
The Scenario things that I want to do is like follows..
First of all, My development circumstance is entityframework and mvc3.
When Someone logged in each one has different database. So, Each has connect different database.
So, Each person has his own session value which is database connection string. So far so good.
I have simple database Repository and at the each repository's constructor can change database connection.
At controller which calls Repository class, I need session value. But As I know Controller's construction can't keep session value. right?
I want your good advice. Thanks in advance.
Code samples are below:
public class MasterRepository
{
DBEntities _db;
public MasterRepository(string con)
{
_db = new DBEntities(con);
}
}
public class TestController : Controller
{
private string con;
MasterRepository _db;
public TestController()
{
_db = new MasterRepository(Session["conn"].ToString()); // Session is null I want to solve this Part...
}
public ActionResult Index()
{
string con = Session["conn"].ToString(); // Session is assigned.
return View();
}
}
These should explain what's happening to cause Session to be null, and give you a few possible solution options:
Is ASP.NET MVC Session available at any point durign controller construction
Why my session variables are not available at construction of a Controller?
Session null in ASP.Net MVC Controller Constructors
I think you have missed out the "service" part of the controller - service - repository pattern:
http://weblogs.asp.net/fredriknormen/archive/2008/04/24/what-purpose-does-the-repository-pattern-have.aspx
But when you go down this path you will probably also need to learn IoC as well.
Then your code would look more like:
public class MasterRepository
{
public Foo GetAllFoo()
{
return ObjectContextManager.GetObjectContext().AsQueryable().ToList();
}
}
public class MasterService
{
MasterRepository _repository;
public MasterService(MasterRepository repository) // use IoC
{
_repository = repository;
}
public Foo GetAllFoo()
{
return _repository.GetAllFoo();
}
}
public class TestController : Controller
{
MasterService _service;
public TestController(MasterService service) // use IoC
{
_service = service;
}
public ActionResult Index()
{
var model _service.GetAllFoo();
return View(model);
}
}