How can I add new model MVC in proper way?
I have one model with UsersContext. I want to create another - NewContext.
Is the code below will work without any problems? And maybe there is a better solution to create model in existing database? What exacly mean UsersContext and NewContext in code?
public class NewContext : DbContext
{
public NewContext ()
: base("DefaultConnection")
{
}
public DbSet<test1> test1{ get; set; }
public DbSet<test2> test2{ get; set; }
public DbSet<test3> test3{ get; set; }
}
(...)
Is the code below will work without any problems?
Yes, this will work. The DbContext is used to group the entities you want to work with in your application. In fact you do not need a second context. You could have only one DbContext in which you add all your domain entities as DbSet<T> properties and then work with this context.
Related
i need to import a new table in Nop database, and i need to create the data access layer like others tables.
The table has a primary key column which name is SignatureId and my client don't want to change this name.
So i can't inherit from BaseEntity abstract class because it implies that the primary Key table must call "Id".
My question is :
Is it a problem to create a new Domain entity class who is not inherit from BaseEntity ? Like :
public class Signature
{
public int SignatureId { get; set; }
public string Hash{ get; set; }
public.....
}
Maybe it must implies so problem during entity manipulations ? Can you advice me about that ?
A quick solution would be using both id and signatureId. So you will be inline with your client and nopcommerce.
Repository pattern is used in nopcommerce to store data using base entity. So creating an entity without inheriting from base would break the design.
I am late but the answer is yes you can, even if you inherit from it. You just need to ignore it in the mapping like below;
public class Signature : BaseEntity
{
public int SignatureId { get; set; }
public string Hash{ get; set; }
public.....
}
In the mapping i.e Nop.Data -> Mapping
public class SignatureMap : NopEntityTypeConfiguration<Signature>
{
this.Ignore(c => c.Id);
this.HasKey(c => c.SignatureId);
}
The stock asp.net mvc 5 application creates the application users, aka identity users in a separate context, named a file called "IdentityModels.cs" - it looks like this
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
}
I am attempting to put the Application users in a regular data context, i.e. something like this
public class BlogProphetContext : DbContext
{
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Answer> Answers { get; set; }
public DbSet<Question> Questions { get; set; }
public DbSet<Tag> Tags { get; set; }
}
However, every time I do that I get the following error every time I try to create an account
The UserId field is required
In the AccountController.cs when I attempt to execure the following line of code
result = await UserManager.AddLoginAsync(user.Id, info.Login);
I get the feeling my approach is wrong, and that I cannot have the ApplicationUsers in the main data context file without some sort of external chicanery - does anyone know of some way to do this? All of the files are up to date.
This was a bit too easy - it turns out that all you have to do it remove the
<ApplicationUser>
when you call the context and everything turns out like you might expect (i.e. the MVC assumptions and the developers assumptions (in this case, mine) sync.
Here is is working properly
public class MyContext : IdentityDbContext
{
public MyContext()
: base("DefaultConnection")
{
}
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Answer> Answers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
}
In this case, if you dont want your ApplicationUser to be associated with asp.net Identity the easiest thing would be to just remove the inheritance from the applicationUser class.
Go from ApplicationUser : IdentityUser to just ApplicationUser, then in that class just create an Id property.
You wont have to use IdentityDBContext then.
Of course you will have to totally rewrite AccountController, or get rid of it. You cant use UserManager anyways as thats linked to IdentityUser
Then obviously make sure you add your migration/update database if you are working with EF.
If you do want to keep the account controller as is and keep IdentityDbContext but add other entities then thats easy, just do this:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection")
{
}
public DbSet<Dept> Dept{ get; set; }
public DbSet<Course> Course{ get; set; }
public DbSet<Etc> Etc{ get; set; }
}
Ensure that your ApplicationUser class inherits from IdentityUser.
Then you need to configure your context so that it maps all the ASP.NET Identity classes correctly.
These are:
ApplicationUser (your class)
IdentityUserClaim
IdentityUserLogin
IdentityUserRole
IdentityRole
Details of this is a bit too complicated to post here, but I have made a sample project that works with the release version of ASP.NET Identity. You can see it here:
https://github.com/onybo/Asp.Net-Identity-sample-app/tree/master/CustomUser
I am not sure if this will help you or if i fully understand your questions...but if you want try use your own "model" then change:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("PUT IN YOUR MODEL CONN HERE")
{
}
I do not know how much more than this you can configure or if this will really change the context.
I am having a problem with the Entity Framework code-first approach:
public class Entity
{
[Key]
public int Id { get; set; }
public string A { get; set; }
}
public class Context : DbContext
{
public DbSet<Entity> Entities { get; set; }
}
Let's say this is the setup for the Entity Framework. It works. I can create an Entity instance and Add it to the Entities set. Now my problem is: I want to create a subclass of Entity that is a ViewModel passed to some view:
public class EntityViewModel : Entity
{
public String ViewModelProperty { get; set; }
}
Then, when I get back the resulting object from the model binder, I should be able to do this:
public void Action(EntityViewModel vm)
{
db.Entities.Add(vm); // This should work since EntityViewModel inherits Entity
db.SaveChanges();
}
Here, I get the following Exception:
Mapping and metadata information could not be found for EntityType 'EntityViewModel'.
I already tried adding the [NotMapped] attribute to EntityViewModel, this doesn't help.
If I manually extract the EntityViewModel properties into a new Entity object, it works:
public void Action(EntityViewModel vm)
{
var entity = new Entity
{
Id = vm.Id,
A = vm.A
};
db.Entities.Add(entity); // This works!!!
db.SaveChanges();
}
Why does the EntityFramework behave this way? Is there a way to tell it to ignore EntityViewModel objects?
Thanks in advance.
This will not work because EF understands your inheritance as a Table per Hierarchy scheme, so it expects to have the properties of EntityViewModel on the same table as the properties for Entity.
You can use composition to avoid this problem:
public class EntityViewModel : Entity
{
public Entity Entity { get; set; }
public String ViewModelProperty { get; set; }
}
And then
public void Action(EntityViewModel vm)
{
db.Entities.Add(vm.Entity);
db.SaveChanges();
}
Check this answer for complex objects model binding rules.
Good luck.
A better approach would be to use composition rather than inheritence. In this instance, the view model could either expose the model directly to the view, or delegate through to the model.
I have an ASP.NET MVC App, which use EF code First, for some reason I need to use 2 differents DBContext for my app like the example here:
namespace ESN.Models
{
public class CoreA
{
//..........
}
public class CoreB
{
//..........
}
public class CoreDbContext : DbContext
{
public DbSet<CoreA> CoreA { get; set; }
public DbSet<CoreB> CoreB { get; set; }
}
public class StuffA
{
//..........
}
public class StuffB
{
//..........
}
public class StuffDbContext : DbContext
{
public DbSet<StuffA> StuffA { get; set; }
public DbSet<StuffB> StuffB { get; set; }
}
}
And for the convenient developing I add some code that drop and re-create the database if model has change:
Database.SetInitializer<CoreDbContext>(new DropCreateDatabaseIfModelChanges<CoreDbContext>());
Database.SetInitializer<StuffDbContext>(new DropCreateDatabaseIfModelChanges<StuffDbContext>());
But the issue is they just Create new table for the DbContent that I need to use first, the Core table exist but none of the Stuff!
Thanks for your help!
If you want to use two DbContext types and database initializers each context must use its own database. If you use the same database for both context types you cannot use database initializers and you must maintain the database schema changes manually (you must manually or through some SQL script create database and all necessary tables prior to using the application).
Am having trouble finding a clear answer to my situation when searching Stack Overflow and Google, hopefully someone can point me in the right direction.
My Situation
I want to be able to use a single edit form (in a single View) to update a 3-level-deep hierarchical entity using ASP.NET MVC 3 and Entity Framework 4 CTP (Code-first) - the model consists of Services, which can have many Service Options, which in Turn can have many Inventory Items.
I was expecting to be able to use MVCs default model binder (via TryUpdateModel) to:
Update an existing 'Service' record
Add/Update/Delete 'Service Option' records (attached to the Service) depending on posted values
Add/Update/Delete 'Inventory' records (attached to each Service Option) depending on posted values
My Model
[Bind(Include="Name, ServiceOptions")]
public class Service {
[Key]
public int ServiceID { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<ServiceOption> ServiceOptions { get; set; }
}
[Bind(Include="ServiceOptionID, Description, Tags")]
public class ServiceOption {
[Key]
public int ServiceOptionID { get; set; }
public int ServiceID { get; set; } /* parent id reference */
public string Description { get; set; }
public virtual ICollection<Inventory> InventoryItems { get; set; }
}
[Bind(Include = "InventoryID, Description")]
public class Inventory {
[Key]
public int InventoryID { get; set; }
public int ServiceOptionID { get; set; } /* parent id reference */
public string Description { get; set; }
}
Ideal Controller Method:
[HttpPost]
public ActionResult EditService(int id) {
Service service = db.Services.Single(s => s.ServiceID == id);
TryUpdateModel(service); // automatically updates child and grandchild records
if (ModelState.IsValid) {
db.SaveChanges();
return RedirectToAction("Index");
}
return View(service);
}
Is there a way to achieve this utopian dream, or am I barking up the wrong tree? I'm open to using another technology (such as normal EF4, Automapper etc)
Thanks in advance!
With just the default model binder? Probably not.
With a custom one? Probably.
However your issue won't be the model binder itself. Your issue will be that EF and ORMs and ( I think ) in general do not consider removing an item from a collection as a delete operation. In effect what you are telling the ORM is the relationship does not exist, not that a child row needs to be deleted. Depending on your mappings you'll usually get an error like "A referential integrity constraint violation occurred". This won't be because of code first this is just how EF works.
EF works this way by design and is really important for more complex relationships such as when you have m2m relationships which reference other m2m relationships. You really want EF to be able to disambiguate calls for removal of a relationship and calls to remove a row entirely.
Also, IMHO, this technique is also bad because your letting the piece of code responsible for mapping http values also dictate how objects should be persisted. This is a bad move. I consider delete operations a pretty sacrosanct act and shouldn't be left to the ModelBinder alone. Without soft deletes or logging deleting objects should be considered "serious business".