I would like to only have one DbContext in my ASP.NET MVC project. How should I merge the default IdentityDbContext with my own code first DbContext? They are using the same database.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("SignalRChat")
{
}
}
This is the default one provided in the IdentityModel.cs class.
Is it safe to do the following? And append my own DbSets?
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("SignalRChat")
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Standard> Standards { get; set; }
}
Any advice is much appreciated!
Yes, it is perfectly fine to add DbSet declarations in the DbContext classes. Normally you would maybe create a context for a related group of tables that makes sense when you access it from your repositories, e.g. ApplicationDbContext for user registration, login etc. another for Students and related entities.
If you have many contexts maybe you should check for the bounded context "pattern" https://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DEV-B336#fbid=wH4n-081m_U.
Related
So I started my project using the identity scaffolding and created an application user class that inherits from identity user
using Microsoft.AspNetCore.Identity;
namespace test6.Models
{
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
and some classes that inherit from this class
using Microsoft.AspNetCore.Identity;
namespace test6.Models
{
public class Teacher : ApplicationUser
{
public string Course { get; set; }
}
}
I have set up my roles and they seem to be working fine, however my problem is that I am trying to retrieve data from users and when retrieving data that is specific to a class that has inherited from applicationuser like Course from Teacher I get an error which is because my usermanager is initialised with ApplicationUser
private readonly UserManager<ApplicationUser> _userManager;
The method I'm using to retrieve users is this
[HttpGet]
public async Task<IActionResult> ListTeacher()
{
var users = await _userManager.GetUsersInRoleAsync("Teacher");
return View(users);
}
So I have tried to initialise usermanager with Teacher to test but I get an error I think it's because in the dependancy I used ApplicationUser and I don't think you can use more than one. So my question is what possible solutions are there for this.(Sorry if my question isn't great or my explanation is poor)
Ok I think I've found a solution, turns out you can add another dependancy.
builder.Services.AddIdentityCore<Teacher>()
.AddRoles<IdentityRole>()
.AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<Teacher, IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddDefaultUI();
With this I can initialise usermanager with Teacher and so far it has worked.
I have an MVC 5 project where I have separated out my models into a deparate project, say Project.Models. The Identity (ApplicationUser) model and its DbContext are still in the main project, as appears in the default MVC 5 project scaffold. One of the entities in the Project.Models assembly must have a property that is a list of ApplicationUsers.
Now I am starting to think that separating out the entity models into a separate project was not a good idea, because now I have the entity models and the Idenity models in separate contexts and assemblies.
How can I make a list of ApplicaitonUsers be part of an entity object if these are in separate assemblies? Should I merge the projects back into one assembly and DbContexgt or is there an easy way to solve this? I cannot define a DbSet<MainProject.ApplicationUser> in DbContext of Project.Models because this would mean circular reference.
Thanks.
You can add Identity related packages Microsoft.AspNet.Identity and Microsoft.AspNet.Identity.EntityFramework in your Models project and move ApplicationUser class to models project.
You can also add profile data in ApplicationUser like this:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, string> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
Also, to make it a single DBContext, you can directly inherit from IdentityDbContext in your dbcontext class. Like this:
public partial class MyDBContext : IdentityDbContext<ApplicationUser>
{
public MyDBContext()
: base("name=DefaultConnection", throwIfV1Schema: false)
{
}
}
This way you wouldn't need to define DbSet<MainProject.ApplicationUser> in your context class.
I'd appreciate if someone could give an advice on building the right architecture for ASP.NET MVC web app.
I'm currency working on MVC 5 web application, with ADO.NET Entity Data Model which uses existing database. The application mainly uses CRUD operations.
I've doubts on the design pattern I'm trying to use in order to reach loose coupling. I'd also like to use Ninject dependency injector.
So, my solution includes 3 projects: Abstractions, MVCWebApplication and DAL.
I'd like to get a suggestions on structuring the Abstractions project.
Firstly, I've defined the view models for my db entities. I don't use Adapter pattern, instead I'll use AutoMapper to map DB and View model classes:
namespace MVCWebApplication.Models
{
public class CustomerVM
{
public int ID {get; set;}
public string Name {get; set;}
public Contract Contract {get; set;}
}
public class ContractVM
{
public string ContractNo {get; set;} //ID
pulic DateTime AgreementDate {get; set;}
}
}
Generic repository
namespace Abstractions
{
public interface IRepository<T>
{
T Find(object pk);
IQueryable<T> GetAll();
void Insert(T entity);
//...
}
public class Repository<T> : IRepository<T> where T : class
{
public DbContext context;
public DbSet<T> dbset;
public Repository(DbContext context)
{
this.context = context;
dbset = context.Set<T>();
}
//implementation
}
}
And UnitOfWork which gives me an access to the repositories:
namespace Abstractions
{
public interface IUnitOfWork : IDisposable
{
IRepository<Customer> CustomerRepository { get; } //Customer is DB entity
IRepository<Contract> ContractRepository { get; } //Contractis DB entity
//other repositories
void Save();
}
public partial class UnitOfWork : IUnitOfWork
{
private IRepository<Customer> _customerRepository;
private IRepository<Contract> _contractRepository;
private CREntities _context;
public UnitOfWork()
{
_context = new CREntities();
}
public IRepository<Customer> CustomerRepository
{
get
{
if (_customerRepository == null)
_customerRepository = new Repository<Customer>(_context);
return _customerRepository;
}
}
//other repositories, save & dispose ..
}
}
In App_Start I've got:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
}
So, my question is this approach expedient? What is the sense of Ninject here?
Thanks a lot
My view on your approach, its nice and there are many people around using it in big applications. So do not worry.
One suggestion, in your above code, you can use IRepository directly instead of using UnitOfWork.XXXRepository. You got generic repository, it will work with any entity (customer, contract, or a new entity)
With having UnitOfWork class the problem is, when you need another repository (for a new entity), you will need to change UnitOfWork class (breaks Open Close Principle).
What is the sense of Ninject here?
I am not sure if I understand your question fully, Ninject is allowing you to set up your dependencies at one single place and then at runtime injecting these dependencies in your controller or services or wherever used.
I have an issue that I have been struggling with. I would appreciate any help
So, I have an application that uses Code first. For authentication, I use Asp.Net Identity 2.0.1. So I have a User class that derives from Identity User like this:
public class User: IdentityUser
{
public virtual UserInfo UserInfo { get; set; }
public virtual Organization Organization { get; set; }
}
Then i define my Context as:
public class IdentityContext: IdentityDbContext<User>
{
public IdentityContext(): base("Name=IdentityContext")
{
}
static IdentityContext()
{
Database.SetInitializer<IdentityContext>(new CreateDatabaseIfNotExists<IdentityContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new UserMap());
modelBuilder.Configurations.Add(new UserInfoMap());
}
}
Then i enable migrations using this context. And since Organization class is linked to User it also is added to the migration. But I dont want that, since its different from the Identity classes. My Organization class is as follows:
public partial class Organization: EntityBase
{
public Organization()
{
this.Users = new List<User>();
}
public int OrganizationId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public virtual ICollection<User> Users { get; set; }
}
This derives from EntityBase and not from IdentityUser class and is handled differently.
What I would be able to do is to handle all my non-identity classes through a different context, lets say AppContext that could be defined as:
public class AppContext: DbContextBase
{
public AppContext(): base("Name=IdentityContext")
{
}
static AppContext()
{
Database.SetInitializer<AppContext>(new CreateDatabaseIfNotExists<AppContext>());
}
public new IDbSet<T> Set<T>() where T : class
{
return base.Set<T>();
}
protected override void OnModelCreating(DbModelBuilder builder)
{
builder.Configurations.Add(new OrganizationMap());
}
}
And then enable a second migration for this context.
But when I enable a second migration it fails with the exception that "Migrations have already been enabled in project 'Datastore'. To overwrite the existing migrations configuration, use the -Force parameter.". Although it still creates the Configuration file for the second migration.
So when i try to add a migration for this configuration it complains the following:
One or more validation errors were detected during model generation:
Datastore.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no
key defined. Define the key for this EntityType.
Datastore.IdentityUserRole: : EntityType 'IdentityUserRole' has no key
defined. Define the key for this EntityType.
Datastore.UserInfo: : EntityType 'UserInfo' has no key defined. Define the key for this
EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type >'IdentityUserLogin' that has no> keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type >'IdentityUserRole' that has no
keys defined.
UserInfoes: EntityType: EntitySet 'UserInfoes' is based on type 'UserInfo' that has no >keys defined.
I am not sure how to get around this? Any help is really appreciated
The idea was to inherit the AppContext with IdentityDbContext. IdentityDbContext itself inherits from DbContext so it has all the functionality available for DbContext plus extra configuration requirements for the Asp.Net Identity framework
I have an asp.net website and I would like to organize it into three layers
DataAccess
Domain
UI
What specifically goes in each of these layers?
e.g
Data
- Models
- Repositories? Would that be just interfaces
- IoC?
Domain
- Services?
UI
- javascript
- Area specific models?
- css
Could someone provide a simple guideline for organizing an asp.net website like this?
As other people have said each situation is different, but for a basic architecture, I would probably go along with something like this. It has gotten me out of a few jams and up and running quite quickly.
Infrastructure Layer
This is where all the data access is done. Database connection management, etc.
The Repositories include all queries to the database.
The Dependency Resolution sits here too. Use your DI Container of choice.
Domain Layer
This is where all you business logic sits.
The Domain Services Interfaces are what the UI layer call to use your business logic
UI
Pretty obvious this one....
Code Example
--UI
public class MyController
{
private readonly IMySerivce _myService;
public MyController(IMySerivce myService)
{
_mySerivce = myService;
}
public void MyAction()
{
_myService.DoSomeAction();
}
}
--Domain
public Interface IMyService()
{
void DoSomeAction();
}
public class MySerivce : IMyService()
{
private readonly IMyRepository _myRespository;
public MySerivce(IMyRepository myRepository)
{
_myRepository = myRepository;
}
public void DoSomeAction()
{
_myRepository.Save();
}
}
public interface IMyRepository
{
void Save();
}
--DataLayer
public MyRepository : IMyRepository
{
public void Save()
{
//Manage Save here
}
}
Additionally I usually have a separate area for unit/integration tests.
Update
This most definitely is dependent on your situation. It is very hard to say what method is best without fully understanding what you are ultimately trying to build.
From the list below you can see which method works well for you or fits well with your architecture.
Regardless of which one you choose, your Repository Implementation will have to have a dependency on your Domain Objects project.
Some techniques in doing it include:
No Mapping
Your Domain Objects really then become dummy mappings to your tables. i.e. have a table in your database call User. Then have a Domain Object called User. This is by far the simplest technique.
--Domain
public class User
{
public int Id {get; set;}
public string UserName {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string Password {get; set;}
}
--Infrastructure
public class UserRepository : IUserRepository
{
public Core.User GetById(int id)
{
return DBConnection.GetByIdQuery(id);
}
}
Mapping
Martin Fowler describes it here
It is possible in your infrastructure layer to have what are known as Domain Transfer Objects (DTO) that represent your database tables. Similar to above, a table called User, a DTO called User. Both having the same properties.
Your domain Entity then becomes a true representation of your domain and business logic.
The mapping of the DTO to your Domain Entity (search query) can be done in the Repository and the mapping of your Domain Entity to your DTO (save/update query) would also be done in your Repository.
To do your mapping you can either create custom mapping classes or use 3rd party tools like AutoMapper. I am a big fan of AutoMapper.
A sample code example would be along the lines of:
--Custom mapper
public class UserRepository : IUserRepository
{
private readonly IUserMapper _userMapper;
public UserRepository(IUserMapper userMapper)
{
_userMapper = userMapper;
}
public Domain.User GetUserById(int id)
{
var DtoUser = GetUserByIdQuery(int id);
return _userMapper.MapUserDTOToDomainEntity(DtoUser);
}
}
public class UserMapper : IUserMapper
{
public Domain.User MapUserDTOToDomainEntity(DataEntity.User dtoUser)
{
//Manual property mapping
}
}
--AutoMapper Example
public class UserRepository : IUserRepository
{
public Domain.User GetUserById(int id)
{
var DtoUser = GetUserByIdQuery(int id);
return Mapper.Map<Domain.User>(DtoUser);
}
}
Other examples include:
https://stackoverflow.com/questions/14724612
There are many many debates out there in blogs and here on SO about the value of DTO's,
including MSDN, this blog and these https://stackoverflow.com/questions/11237946, https://stackoverflow.com/questions/15148866