So I've got these 2 class and User coming from individual user accounts
public class User : IdentityUser
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Email { get; set; }
public virtual ICollection<Basket> Baskets { get; set; }
}
public class Basket
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Key]
public int BasketId { get; set; }
public string Name { get; set; }
public int Words { get; set; }
public virtual ICollection<User> Users { get; set; }
}
EF has created UserBaskets with 2 FK. I have items in my Basket class that I seeded.
My question is, how can I add row to my junction table in the controller? For example, a logged user click on a basket and return the Id...Now I've got
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Basket(int? basketid)
{
if (ModelState.IsValid)
{
var job = User.Identity.GetUserId();
job.Baskets.Add(basketid);
db.Users.Add(job);
db.SaveChanges();
return RedirectToAction("Basket");
}
return View(db.Baskets.ToList());
}
Thank you for any help.
I finally chose to add a junction table manually
public class UserBasket
{
[Key]
public int UserBasketId { get; set; }
public virtual User User { get; set; }
public virtual Basket Basket { get; set; }
public DateTime Date { get; set; }
}
and could add a row using identityUser like this
UserManager<User> userManager = new UserManager<User>(new UserStore<User>(db));
var user = userManager.FindById(User.Identity.GetUserId());
Basket basket = db.Basket.Find(id);
var userbasket = new UserBasket {User = user, Basket = basket, Date = DateTime.Now };
db.UserBasket.Add(userbasket);
db.SaveChanges();
Related
I want to save student's data in student table and their address in student details table i can't insert data in second table.
Error is Object reference not set to an instance of an object.
Student Model
public partial class Student
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
}
StudentDetails
public partial class StudentDetail
{
public int Id { get; set; }
public string Address { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
}
View Model
public class StudentViewModel
{
public Student Students { get; set; }
public StudentDetail StudentDetails { get; set; }
}
DbSet
public partial class SampleEntities : DbContext
{
public SampleEntities()
: base("name=SampleEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public System.Data.Entity.DbSet<Basics.Models.Student> Students { get; set; }
public System.Data.Entity.DbSet<Basics.Models.StudentDetail> StudentDetails { get; set; }
}
Controller
private SampleEntities db = new SampleEntities();
Action
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(StudentViewModel model)
{
if (ModelState.IsValid)
{
model.Students.CreatedDate = DateTime.Now;
db.Students.Add(model.Students);
db.SaveChanges();
//The Newly created Id gets created and when saving that Id in anothr table the exception comes
model.StudentDetails.Id = model.Students.Id;
//For Time Being in real time it won't be hard coded
model.StudentDetails.Address = "New Jersey";
db.StudentDetails.Add(model.StudentDetails);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model.Students);
}
Why not have
public StudentDetail StudentDetails { get; set; }
in Student class and change Id for
public int StudentId { get; set; }
and then change Id in StudentDetail for also
public int StudentId { get; set; }
Like that Entity Framework will be able to join them in a 1 to 1 relationship. You'll have to add some primary keys/foreign keys depending on your needs.
I am new to Entity Framework and Asp.NET, and therefore, struggling with creating database relationships within the Entity Framework.
I have two SQLite tables (Ticket and User) and have setup my entity models as follows:
public class Users
{
[ForeignKey("id")]
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public int? assigned_to { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
public virtual Users Users { get; set; }
}
I am trying to use Entity Framework 7 to export an IEnumerable<Tickets> that includes the User assigned to each Ticket.
I have tried to create my model relationship in MyDBContext as a single User can have multiple Tickets, and also has a foreign key associated in my Sqlite database (Tickets.assigned_to = User.id):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne(e => e.Users)
.HasForeignKey(p => p.assigned_to);
}
My result ends up with Ticket data being exported, but against every ticket I see a null value for User:
[{"id":10002,...,"Users":null}]
When I use .Include() within my Repository to include each User like this:
public IEnumerable<Tickets> GetAll()
{
return _db.Tickets.Include(t => t.Users).ToList();
}
It results in the error
HTTP Error 502.3 - Bad Gateway
The specified CGI application encountered an error and the server terminated the process.
What I'm trying to retrieve is data that looks like:
{"Ticket";[{"id":10002,..."status":"closed"}],"Users":[{"id":"1"..."email":"johndoe#someplace.com"}]}
I know it probably has something to do with my relationship model, but I cannot work out what I am doing wrong.
First you should really derive your Users from IdentityUser. It helps when trying to wire up the relationship, but I will give you the answer based on your current models. Your ForeignKey property should be on the child entity. By naming conventions, which is what EF uses by default, your public Users Users works better if you put a public int UsersId. Then essentially what EF will do is from your public Users Users it will go to the Users table. Then it looks for the ForeignKey which is set to Id, so now we are in the Users Table looking at the id property. Then it looks for the naming convention UsersId and if it sees it, it will set that property to the value that it saw from the Users Table Id column.
Try using this
public class Users
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
[ForeignKey("Id")]
public int UsersId { get; set; }
public virtual Users Users { get; set; }
}
and for your Fluent API configuring
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne();
}
Now all that does is create the relationship. In order to view the specific items you want to view, use a ViewModel. So, pull the two lists you want from where you want. Then use logic to separate the list how you want them to display.
public class UsersViewModel()
{
public UsersViewModel(Users user, List<Tickets> tickets)
{
this.first_name = user.first_name;
this.last_name = user.last_name;
this.email = user.email;
this.Tickets = new List<Tickets>();
foreach(var ticket in tickets)
{
if(ticket.UserId == user.Id)
{
this.Tickets.Add(ticket)
}
}
}
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public List<Tickets> Tickets { get; set;}
}
then in your controller make your list
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var ticketsList = _repository.Tickets.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
or use a Linq query
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var ticketsList = from x in _repository.Tickets where x.UserId.Equals(user.Id) select x;
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
then at the top of your view you should have
#model IEnumerable<UsersViewModel>
I have those 2 Models
public class BranchEmployees
{
public int ID { get; set; }
[Required, Column(Order = 0), Key]
public string ApplicationUserID { get; set; }
[Required, Column(Order = 1), Key]
public int BranchID { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
public virtual ICollection<Branch> Branch { get; set; }
}
public class Branch
{
public int ID { get; set; }
public string BranchName { get; set; }
[Required]
public string ApplicationUserID { get; set; }
public ApplicationUser User { get; set; }
public virtual ICollection<BranchEmployees> BranchEmployees { get; set; }
}
public class ApplicationUser
{
//rest of the code
}
UPDATE
I have everything set up but what I want is the query that gets me the Employees whose IDs are in the branch employees table
, I'm using entity framework code first with MVC 5 , how do I do it ?
Assuming that your ApplicationUser class will have a navigational property called BranchEmployees, here is the query that gets me the Employees whose IDs are in the branch employees table
List<ApplicationUsers> employeeNames =
dbContext
.ApplicationUsers
.Where(au => au.BranchEmployees
.Count() > 0).ToList();
Also, can you provide whole model including ApplicationUser? I also wonder why you do not prefer BranchEmployees to inherit from ApplicationUser.
You don't need a class that indicates a many-to-many relation between two tables when you do code-first. The key here is to create virtual properties of those classes. Lets say you have a class Student and class Course. Students can be in many Courses and Courses can have many Students. To generate a database using these models the classes should look like this:
public class Student
{
private ICollection<Course> _courses;
public Student()
{
this._courses = new HashSet<Course>();
}
[Key]
public int Id { get; set; }
public string FullName { get; set; }
public virtual ICollection<Course> Courses
{
get { return this._courses; }
set { this._courses = value; }
}
}
And for Course:
public class Course
{
private ICollection<Student> _students;
public Course()
{
this._students = new HashSet<Student>();
}
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Student> Students
{
get { return this._students; }
set { this._students = value; }
}
}
I hope that this can help you solve your issue.
I'm building an application using ASP.NET MVC4 with code first data migrations. I have an estimates model, a clients model, a DbContext, and a view model I created. I am wanting to display the company name in a drop down, with the company name tied to an estimate. I have a ClientId in both models. I also created a DbSet<> and that didn't work either when querying against it.
I tried to create a viewmodel that I thought I could simply query against and display through my controller. I'm not having any luck in getting this to work. After a day plus of looking on here and other places, I'm out of ideas.
How can I query/join the two models, or query the viewmodel to get the company name associated with the clientId? Thanks for the help.
Models:
public class Estimates
{
[Key]
public int EstimateId { get; set; }
public int ClientId { get; set; }
public decimal EstimateAmount { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime EstimateDate { get; set; }
public string EstimateNotes { get; set; }
}
public class Clients
{
[Key]
public int ClientId { get; set; }
public string CompanyName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public ICollection<Estimates> Estimates { get; set; }
public ICollection<Contracts> Contracts { get; set; }
}
public class ClientEstimateViewModel
{
public Clients Clients { get; set; }
public Estimates Estimates { get; set; }
}
public class NovaDb : DbContext
{
public NovaDb(): base("DefaultConnection")
{
}
public DbSet<Clients> Clients { get; set; }
public DbSet<Estimates> Estimates { get; set; }
public DbSet<Contracts> Contracts { get; set; }
public DbSet<Invoices> Invoices { get; set; }
public DbSet<ClientEstimateViewModel> ClientViewModels { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Controller:
NovaDb _db = new NovaDb();
ClientEstimateViewModel ce = new ClientEstimateViewModel();
public ActionResult Index()
{
var model =
(from r in ce.Clients
join x in ce.Estimates
where
//var model =
// from r in _db.Clients
// orderby r.CompanyName ascending
// select r;
return View(model);
}
Because you've created the relationship between client & estimate in your models, you should be able to create a query like this:
var query = from c in _db.clients
select new ClientEstimateViewModel
{
Clients = c,
Estimates = c.Estimates
}
Although you'd have to change your model so Estimates was public List<Estimates> Estimates { get; set; }
This would give you a collection of ClientEstimateViewModel which you could then pass to your view
I'm using asp.net mvc 4, EF, codefirst to make a many to many relation to a users and roles system
the user model:
public class User
{
#region properties
[Key]
public Int32 Id { get; set; }
[Required]
public String UserName { get; set; }
public String Password { get; set; }
[Required]
public String Email { get; set; }
public DateTime CreationDate { get; set; }
public DateTime LastUpdate { get; set; }
public DateTime? LastLogin { get; set; }
[ForeignKey("RoleId")]
public virtual ICollection<Role> Roles { get; set; }
#endregion //properties
#region constructors
public User()
{
Roles = new HashSet<Role>();
LastUpdate = DateTime.Now;
CreationDate = DateTime.Now;
}
#endregion //constuctors
}
the role model:
public class Role
{
[Key]
public Int32 Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public DateTime CreationDate { get; set; }
public DateTime LastUpdate { get; set; }
[ForeignKey("UserId")]
public virtual ICollection<User> Users { get; set; }
public Role()
{
Users = new HashSet<User>();
CreationDate = DateTime.Now;
LastUpdate = DateTime.Now;
}
}
the context:
public class UserManagementContext : Context, IContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public UserManagementContext() {
Database.SetInitializer<UserManagementContext>(null);
}
void IContext.Setup(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<Role>().ToTable("Roles");
modelBuilder.Entity<User>()
.HasMany(u => u.Roles)
.WithMany(r => r.Users)
.Map(
m =>
{
m.MapLeftKey("UserId");
m.MapRightKey("RoleId");
m.ToTable("UserRoles");
});
}
}
When the database tables are generated the tables users, roles and userroles are there. Then I make a record in users, one in roles and one in userroles to connect those. The userroles table has two columns RoleId and UserId.
Then I try to load the roles of a user like this:
public String[] GetRoles(String userName)
{
//var user = ConcreteContext.Users.Include("Roles").Where(u => u.UserName == userName).FirstOrDefault();
var users = ConcreteContext.Users.Include(u => u.Roles);
var user = users.FirstOrDefault();
var roles = from r in user.Roles
select r.Name;
return roles.ToArray();
}
But the line with var users = ConcreteContext.Users.Include(u => u.Roles); raises the next error:
System.Data.SqlClient.SqlException: Invalid object name 'dbo.RoleUsers'.
If I change de table name of UserRoles to RoleUsers when de database is created (by using m.ToTable(RoleUsers) ), I get a lot of different errors about wrong field names.
Anyone an idea what I'm missing here?
Thanks in advance,
Willem
Any reason why you have to use the Fluent API?
You can map Many-to-many like this with data attributes:
public class User
{
[InverseProperty( "Users" )]
public virtual ICollection<Role> Roles {get;set;}
}
public class Role
{
[InverseProperty( "Roles" )]
public virtual ICollection<User> Users {get;set;}
}
This will do what I needed:
public class User
{
#region properties
[Key]
public Int32 Id { get; set; }
[Required]
public String UserName { get; set; }
public String Password { get; set; }
[Required]
public String Email { get; set; }
public DateTime CreationDate { get; set; }
public DateTime LastUpdate { get; set; }
public DateTime? LastLogin { get; set; }
[InverseProperty("Users")]
public virtual ICollection<Role> Roles { get; set; }
#endregion //properties
#region constructors
public User()
{
LastUpdate = DateTime.Now;
CreationDate = DateTime.Now;
}
#endregion //constuctors
}
public class Role
{
[Key]
public Int32 Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public DateTime CreationDate { get; set; }
public DateTime LastUpdate { get; set; }
[InverseProperty("Roles")]
public virtual ICollection<User> Users { get; set; }
public Role()
{
CreationDate = DateTime.Now;
LastUpdate = DateTime.Now;
}
}
public class UserManagementContext : Context, IContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public UserManagementContext() {
Database.SetInitializer<UserManagementContext>(null);
}
void IContext.Setup(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<Role>().ToTable("Roles");
}
}