Merge ApplicationDbContext and DataContext into a single context - asp.net-mvc-5

I am having a problem merging these 2 contexts.
I deleted this line of code from IdentityModels.cs:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
I implemented this inside my DataContext.cs
public class DataContext : DbContext
{
public DataContext()
: base("name=DefaultConnection")
{
}
// Account tables
public DbSet ApplicationUsers { get; set; }
public DbSet Roles { get; set; }
public DbSet Tokens { get; set; }
public DbSet UserClaims { get; set; }
public DbSet UserLogins { get; set; }
public DbSet UserManagements { get; set; }
public DbSet UserRoles { get; set; }
public DbSet UserSecrets { get; set; }
// App Models
public DbSet<Course> Courses { get; set; }
public DbSet<Student> Students { get; set; }
}
Problem:
When I "update-database" it only created the Courses and Students tables.
Question
If I successfully implement this method will I lose all of the nice methods that IdentityDbContext interface offers for example:
var rm = new RoleManager<IdentityRole>(
new RoleStore<IdentityRole>(new ApplicationDbContext()));
return rm.RoleExists(name);

Ok here is the solution that I found posted by Olav Nybo in this topic How can one put application users in the same context as the rest of the objects?.
Go to his sample project on github: https://github.com/onybo/Asp.Net-Identity-sample-app/tree/master/CustomUser/CustomUser
Download the configurations folder from the Models folder and place the folder inside your models folder.
Inside your DataContext file you will put this snippet of code which will call these configuration files to build out your database.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
throw new ArgumentNullException("modelBuilder");
modelBuilder.Configurations.AddFromAssembly(typeof(Generic_Repo_Template.Models.Configurations.ApplicationUserConfiguration).Assembly);
}
Now that your database is created you still do not have access to these tables through the datacontext object. In order to be able to access these tables through your datacontext is to include these lines of code:
public virtual IDbSet<ApplicationUser> Users { get; set; }
public virtual IDbSet<IdentityRole> Roles { get; set; }
public virtual IDbSet<IdentityUserClaim> Claims { get; set; }
So the full DataContext file will look something like this:
public class DataContext : DbContext
{
public DataContext()
: base("name=DefaultConnection")
{
}
// Account tables
public virtual IDbSet<ApplicationUser> Users { get; set; }
public virtual IDbSet<IdentityRole> Roles { get; set; }
public virtual IDbSet<IdentityUserClaim> Claims { get; set; }
// App Models
public DbSet<Course> Courses { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
throw new ArgumentNullException("modelBuilder");
modelBuilder.Configurations.AddFromAssembly(typeof(AspNetRoleBasedSecurity.Models.Configurations.ApplicationUserConfiguration).Assembly);
}
}

You have to use:
DbSet<Model> Name {get;set;}
Instead of
DbSet Model {get;set;}
As the answer to your question. The RoleStore needs a DbContext (IdentityDbContext inherits from DbContext). So you should be able to still use the roleManager and more...

Related

How to fix 'model code generator' in asp.net mvc 5

I modelling a simple library management system that able to register user and the user can issue a book.
I want the asp.net IdentityUser to create one -to many relationShip with BookIssue Custom table. because I am new to asp.net mvc 5, I can not fix the problem please help me.
public class ApplicationUser : IdentityUser
{
public virtual ICollection<BookIssue> BookIssues { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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;
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<Book> Books { get; set; }
public DbSet<BookIssue> BookIssues { get; set; }
public DbSet<Catagory> Catagories { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BookIssue>()
.HasRequired(n => n.ApplicationUser)
.WithMany(a => a.BookIssues)
.HasForeignKey(n => n.ApplicationUserId)
.WillCascadeOnDelete(false);
}
}
}
BookIssue Model:
public int BookIssueId { get; set; }
public int BookId { get; set; }
public int ApplicationUserId { get; set; }
public string Email { get; set; }
public DateTime FromDate { get; set; }
public DateTime ToDate { get; set; }
public virtual Book Book { get; set; }
public virtual ApplicationUser ApplicationUser { get; set;
The generated error:
There was an error running the selected code generator. 'Unable to
retrieve metadata for Librart.Models.BookIssuee'.One or more
validation errors were detected during model generation:
Library.Models.IdentityUserLogin: EntityType 'IdentityUserRole' has no
key defined.Define the key for this EntityType.
Library.Models.IdentityUserRole: EntityType 'IdentityUserLogin' has no
key defined.Define the key for this EntityType.
And many other errors are generated.

How to give a Table name in Entity Framework by code first approach in .Net Framework 4.0?

In .NET 4.0 framework the System.ComponentModel.DataAnnotations.Schema doesn't work or doesn't support I think.
I am using a code-first approach and my database already exists, and also not using ADO.net Entity Data Model.
I already used the [Table] attribute and DatabaseGenerated attribute, it's not working causing a compilation error to occur.
This is my code:
Entity class:
public class myclass
{
public myclass()
{
//
// TODO: Add constructor logic here
//
}
[Key]
public int RECORDID { get; set; }
public string AA { get; set; }
public string CAT { get; set; }
public string CS { get; set; }
public int? FS { get; set; }
public int? CA { get; set; }
public int? DR { get; set; }
public int? UM { get; set; }
public int? ID { get; set; }
public double LAT { get; set; }
public double LON { get; set; }
public int? NIC { get; set; }
}
DbContext class:
public class classContext : DbContext
{
public classContext() : base("name=DBConnection")
{
//Disable initializer
Database.SetInitializer<classContext>(null);
}
public DbSet<myclass> myclasses { get; set; }
}
Or I have to add this override method of model creating, is it helpful or not?
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<myclass>().ToTable("Datatbl");
}
Help me out. Thanks
You can Use Table attribute over your class:
[Table("Datatbl")]
public class myclass
{
}

how do i use AutoMapper in ICollation<> Fields

when i use AutoMapper for mapping my ViewModels and get All News, thrown error for me.
Errors...
The following property on Mosque.Core.ViewModels.CategoryViewModel cannot be mapped:
Categories
Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type Mosque.Core.ViewModels.CategoryViewModel.
please help me, thank you
//Models
public class News
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual User User { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<News> News { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<News> News { get; set; }
}
//ViewModels
public class NewsViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<CategoryViewModel> Categories { get; set; }
public virtual UserViewModel User { get; set; }
}
public class CategoryViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<NewsViewModel> News { get; set; }
}
public class UserViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<NewsViewModel> News { get; set; }
}
how do i use for select All News?
--Update1--
I used onion architecture in the project and i installed AutoMapper in the Service layer and i want get all news from repository and fill into ViewModels and pass to the UI.
my code in service layer is...
public List<NewsViewModel> GetAll()
{
Mapper.CreateMap<News, NewsViewModel>()
.ForMember(dest => dest.Categories, src => src.MapFrom(p => p.Categories))
.ForMember(dest => dest.User, src => src.MapFrom(p => p.User));
Mapper.AssertConfigurationIsValid();
var viewModels = new List<NewsViewModel>();
foreach (var item in _newsRepository.GetAll())
{
var viewModel = Mapper.Map<News, NewsViewModel>(item);
viewModels.Add(viewModel);
}
return viewModels;
}
You don't seem to have created maps for Catagory and User.
Add the following maps:
Mapper.CreateMap<User, UserViewModel>();
Mapper.CreateMap<Category, CategoryViewModel>();
By the way, why are you creating the maps inside the GetAll method? You can create the maps once, usually at application startup.

EF 6.1.3 Lazy loading not working

I am trying to get a single employee record, but looking at the Diagnostic Tools it is showing Entity Framework performing tons of queries loading the entire database. Lazy loading is enabled and I am using the public and virtual keywords so I don't think that should be the problem. Is there anything I am missing, the navigational properties for the Employee record should not be loading.
Service:
return _employeeRepo.GetEmployee(sid);
Repository:
public Employee GetEmployee(string sid)
{
Employee employee = Context.Employees.SingleOrDefault(e => e.SID == sid);
return employee != null ? employee.ToDomain() : null;
}
Employee Model:
public class Employee
{
...
public virtual ICollection<Address> Addresses { get; set; }
public virtual ICollection<Disability> Disabilities { get; set; }
...
public virtual Bureau Bureau { get; set; }
public virtual Division Division { get; set; }
...
public Domain.Models.Employee ToDomain()
{
return Mapper.Map<Domain.Models.Employee>(this);
}
}
Context:
public class SqlContext : DbContext
{
public SqlContext() : base("SqlContext")
{
Database.SetInitializer<SqlContext>(null);
}
public virtual DbSet<EfModels.Address> Addresses { get; set; }
public virtual DbSet<EfModels.Bureau> Bureaus { get; set; }
public virtual DbSet<EfModels.Disability> Disabilities { get; set; }
public virtual DbSet<EfModels.Division> Divisions { get; set; }
public virtual DbSet<EfModels.Employee> Employees { get; set; }
}
Your Mapping Tool (AutoMapper) is the issue.
When your calling employee.ToDomain(), the navigation properties of your entity are being accessed, causing EF to lazy load the tables.

DDD/CQRS, Entity has access to Query, Command?

public class PageRoleService
{
public void SetRoles(Page page, User activeUser)
{
var rb = page.Project.ProjectType.GetRoleFor(activeUser.UserType);
page.RolesForPage.Add(activeUser, rb);
var managers = GetAllManagersOf(activeUser);
foreach (var m in managers)
{
page.RolesForPage.Add(m, rb);
}
}
}
public class Project : Entity
{
public ProjectType ProjectType { get; set; }
public IList<Page> Pages { get; set; }
}
public class Page : Entity
{
public string Name { get; set; }
public Project Project { get; set; }
public IDictionary<User, RoleBehaviour> RolesForPage { get; set; }
}
public class ProjectType : Entity
{
public IQueryProcessor QueryProcessor { get; set; }
public IList<RoleBehaviour> RoleBehaviours { get; set; }
public RoleBehaviour GetRoleFor(USerType userType)
{
var behaviour = return QueryProcessor.Execute(new GetRolesByUserAndProjectTypeQuery() {
ProjectType = this,
UserType = userType
});
// Filter behaviour attributes for project type properties, business rules, etc...
// FilterBehaviour(behaviour);
return behaviour;
}
}
public class GetRolesByUserAndProjectTypeQuery
{
public UserType UserType { get; set; }
public ProjectType ProjectType { get; set; }
}
public class GetRolesByUserAndProjectTypeQueryHandler
{
public Db Db { get; set; }
public RoleBehaviour Execute(GetRolesByUserAndProjectTypeQuery query)
{
return Db.FirstOrDefault(r => r.UserType == query.UserType && r.ProjectType == query.projectType);
}
}
public class RoleBehaviour : Entity
{
public Role ROleForArea1 { get; set; }
public Role ROleForArea2 { get; set; }
public UserType UserType { get; set; }
public ProjectType ProjectType { get; set; }
public IDictionary<string, string> Attributes { get; set; }
}
public enum UserType
{
A,
B,
C,
D
}
public class Role : Entity
{
public IList<string> Permissions { get; set; }
}
I don't use repository, no need data abstraction, I use CQRS for crud operations. (CreateProjectCommand, GetRolesByUserAndProjectTypeQuery, etc..)
Users related a lot of project and page. Users have more than role for each Page Entity and is dynamically created when user (client) request to fetch All projects page or single page item.
My Page Role Service determinates page roles for active user and its managers. My MVC Controller use PageRoleService.
PageRoleService is Application Service or Domain Service or .....?
QueryProcessor in Entity (ProjectType) is invalid approach? How can handle this/their problems without lazy or eager loading?
RoleBehaviour is Entity or Value Object?
PageRoleService is a service or business logic in domain?
I know that I'm some years later, but:
I would put away the base class Entity, because it looks that this are just Dtos returned by the queryhandler (infact GetRolesByUserAndProjectTypeQueryHandler.Execute returns a RoleBehaviour).
Given this, I think that:
PageRoleService is a simple service that completes a Dto, hence it looks a kind of factory
Given that ProjectType here has two different roles (a Dto and Entity, and this is against CQRS), if:
it's a Dto, then use a service/factory/ORM to load extra data on it
it's an Entity, try to load all the data that's needed by it. This because there're great changes that you'll need it on the way to execute your command (great explanation about DDD and entities).
The object has it's own identity? Has it an Id that, even if things will change, remains the same? Looking at it, it looks just a Dto, with nothing really interesting (at business level).
see 1.

Resources