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.
Related
I have 2 model classes:
Customer.cs with name and Id
Movies.cs with name and Id
I tried to run enable-migrations, but I got this error:
No context type was found in the assembly WebApplication2'.
Then I saw some answers on websites and people told to make a DBContext class. I do not have any DBContext class as I just made a new MVC project.
So, I tried to make a DbContext class of my own as follows:
{
public class MyDBContext:DbContext
{
public void MyDbContext()
{
}
}
}
Then I was able to run enable-migrtaions command and Migration folder was created with configuration.cs as follows:
internal sealed class Configuration : DbMigrationsConfiguration<WebApplication2.Models.MyDBContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(WebApplication2.Models.MyDBContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
}
}
}
Now when I run the add-migration Initialmodel the Up() and Down() methods are empty and there are no Identity tables.
Please help !
First off I suggest you refer to creating a new MVC project using Entity Framework. There are a lot of tutorials but here's the Microsoft one which is accurate and pretty complete:
Get Started with Entity Framework 6 Code First using MVC 5
It also includes a section on Migrations, however you don't need Migrations until you have a database and a model that's changing.
I would suggest backing out your Migrations until we're ready for them. Rick Strahl has a good article on how to back them out and get back to a clean state:
Resetting Entity Framework Migrations to a clean State
Finally, your DbContext class has to have a DbSet. A DbSet class is an entity set that can be used for create, read, update, and delete operations. With your DbContext class as it is, Entity Framework has no idea what to do or map.
Change your DbContext class to something like this:
{
public class MyDBContext:DbContext
{
public void MyDbContext()
{
}
public virtual DbSet<Movie> Movies {get; set;}
public virtual DbSet<Customer> Customers {get; set;}
}
This will allow you (say in a Controller) to do something like this to add a new Customer to the database:
var customer = new Customer { name = "John Smith" };
using(var context = new MyDbContext())
{
context.Customers.Add(customer); // adds the customer to the DbSet in memory
context.SaveChanges(); // commits the changes to the database
}
NOTE: I don't recommend creating a DbContext this way in a controller, in the first link on using EF6 with MVC 5 there are better ways.
Hope that helps.
I'm using Unity.MVC for DI in my ASP.NET MVC 4.6 app. I have a service interface passed into the controller and that's working great. Now I want to pass in an interface to the EF context to the service but I'm not sure how to do this. I've read EF has this IObjectContextAdapter that I could pass into my service ctor and that works, but I need to then query the actual tables on inside my service from this context but because it's an IObjectContextAdapter it doesn't know my tables. How do I do this?
public class ContactService : IContactService
{
//private ContactsEntities context;
private IObjectContextAdapter context;
// test ctor
public ContactService(IObjectContextAdapter ctx)
{
context = ctx;
}
// prod ctor
public ContactService()
{
context = new ContactsEntities();
}
List<Contact> GetAllContacts()
{
return (from c in context.ObjectContext.?? // I need to query the Contacts table that would be attached to the actual context I pass in but still keep the decoupling from using an Interface passed into the ctor
}
}
The IObjectContextAdapter is the type of ObjectContext property of DbContext.
You should subclass DbContext e.g. ContactsDatabaseContext
public class ContactsDatabaseContext : DbContext, IContactsDatabaseContext
{
// ...
}
And then just register your ContactsDatabaseContext with your IoC container. Something like this:
container.RegisterType<IContactsDatabaseContext, ContactsDatabaseContext>();
Your ContactsDatabaseContext class and IContactsDatabaseContext interface should have properties of type DbSet<T> that refer to your tables e.g.:
IDbSet<BrandDb> Users { get; set; }
UPDATE:
Since you are using a generated file, then do this:
public partial class ContactsDatabaseContext : IContactsDatabaseContext
{
// Expose the DbSets you want to use in your services
}
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.
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 custom entity (not from entity model), which have a property, wich return collection of EF entities (from entity model):
[DataContract]
public class MyEntity
{
[DataMember]
public List<Role> Roles { get; set; }
}
The 'Role' and 'RolePermission' entities are generated by EF4 from DB.
RolePermission has FOREGIN_KEY to Role, and EF4 was generated association between Role and RolePermission:
Role.RolePermissions --navigate property
RolePermission.Role --navigate property
Also, I have DomainService:
[EnableClientAccess()]
public class MyEntityService : DomainService
{
public List<MyEntity> GetMyEntities()
{
...
myEntityInstance.Roles = <GetRoles>
...
return <collection of MyEntities with Roles>
}
}
When I try to compile this, I get error:
Entity 'UserManager.Web.RolePermission' has a property 'RoleReference' with an unsupported type
When I put [Include] attribute to MyEntity.Roles property, I get the same error and this error:
Property 'Roles' of complex type 'MyEntity' is invalid. Complex types cannot have include members.
when I removed reference from RolePermission to Role (RolePermission.Role navigate property) by hands (from entity model), I get only this error in compile time:
The Entity 'Role' in DomainService 'RolesService' does not have a key defined. Entity types exposed by DomainService operations must have at least one public property marked with the KeyAttribute.
How can I resolve this situation? How can I return my custom object (MyEntity) with filled Roles property from MyEntityService?
A added [key] attr to Role.Metadata, and compile succesfull. But there are no MyEntity.Roles property on the client.
RIA services requires all objects passed back and forth between client to server to have a unique key so it knows which specific object you are modifying.
If you must have your own object as a wrapper for EF objects, just add an id member marked with [key] and maintain that value yourself.
[DataContract]
public class MyEntity
{
[key]
public int Id { get; set; }
[DataMember]
public List<Role> Roles { get; set; }
}
There seems to be something wrong with the design if you need to do that. What is the parent of a group of roles in your application? Why not just query roles?