I am working with the EF Code First library trying to work on an appointment scheduling app.
The model's I have are going to be a Client, Appointment, and AppointmentType...
Basically each Client can have a set of Appointments, and each Appointment can have a single AppointmentType...
The code is as follows:
public class Client
{
[ScaffoldColumn(false)]
public int ClientID { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[EmailAddress]
[Required]
public string Email { get; set; }
[DataType("DateTime")]
public DateTime Birthday { get; set; }
[Required]
public string CellPhone { get; set; }
public string HomePhone { get; set; }
public string Notes { get; set; }
public virtual ICollection<Appointment> Appointments{ get; set; }
public string Name {
get{
return FirstName + " " + LastName;
}
}
public class Appointment
{
[ScaffoldColumn(false)]
public int AppointmentID { get; set; }
[ScaffoldColumn(false)]
public int ClientID { get; set; }
[ScaffoldColumn(false)]
public int AppointmentTypeID { get; set; }
[Required]
public DateTime AppointmentDate { get; set; }
public string Notes { get; set; }
public virtual AppointmentType AppointmentType { get; set; }
public virtual Client Client { get; set; }
}
public class AppointmentType
{
[ScaffoldColumn(false)]
public int AppointmentTypeID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public virtual Appointment Appointment { get; set; }
}
Everything works well when I create an appointment type, and a client, but when I create an appointment I get the following error...
InnerException {"The INSERT statement conflicted with the FOREIGN KEY constraint \"Appointment_Client\". The conflict occurred in database \"Salon.Models.SalonContext\", table \"dbo.Clients\", column 'ClientID'.\r\nThe statement has been terminated."} System.Exception {System.Data.SqlClient.SqlException}
If more details are needed, please let me know...I am just trying to figure out if I am missing anything in the setup.
This is what happens when I debug on the post to create the Appointment...All the ID's are as 0 which is correct, but should the other fields not be null?? Or does it matter...Just not very familiar with how things should look this being my first EF Code First project...
According to your setup, one AppointmentType can only have one Appointment. This is a one-to-one mapping. In this case, you better move the AppointmentType into the Appointment entity. Otherwise, what I believe is more logical, an AppoitmentType can have many Appointments but one Appointment can have only one AppointmentType. Accordingly, you should have a virtual ICollection inside your AppointmentType entity.
public class AppointmentType
{
[ScaffoldColumn(false)]
public int AppointmentTypeID { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Appointment> Appointments { get; set; }
}
I am not sure this is what's causing the problem but it could be. Sometimes mapping faults cause some weird exceptions to be thrown. Give it a try and let me know if your problem gets resolved.
By your constraints AppointmentType and Client cannot be null in Appointment. You can delete constraints or set correct objects in object properties. For example create Client and AppointmentType and then create Appointment for created Client with created AppointmentType
Related
I'm trying to create 1-to-1 relationship between two classes. 1 user has 1 profile picture and 1 profile picture belongs to one user.
the code is as follows.
public class UserImage
{
[Key, ForeignKey("User")]
public int ImageId { get; set; }
public byte [] ImageContentBytes { get; set; }
public string FileName { get; set; }
public string UserId { get; set; }
public string ImagePath { get; set; }
[InverseProperty("UserImage")]
public virtual ApplicationUser User { get; set; }
}
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; }
public string Address { get; set; }
public string Postcode { get; set; }
public string RoleId { get; set; }
public IdentityRole Role { get; set; }
public int CityId { get; set; }
public ICollection<User_Has_Jobs_Posted> UserJobs { get; set; }
public City City { get; set; } // Adding relationship to the user.
public IList<JobPost> jobPosts { get; set; }
[InverseProperty("User")]
public virtual UserImage UserImage { get; set; }
}
The error is saying:
Unable to determine the principal end of an association between the types 'FinalWorkFinder.Models.UserImage' and 'FinalWorkFinder.Models.ApplicationUser'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
In a one-to-one relationship one entry must depend on another, rather then both entries depending on each other.
So in your case an ApplicationUser entry would be valid on its own but a UserImage cannot.
You can fix this by using the Required attribute on the FK like so:
[Required]
public virtual ApplicationUser User { get; set; }
Or you could use fluent api, and do something along the lines of:
modelBuilder.Entity<ApplicationUser>()
.HasOptional(f => f.UserImage)
.WithRequired(s => s.User);
I enabled Code First Migration but after sometime I changed the model properties so when i ran the application the following error is given.
Invalid column name etc...because after migration i changed the model.
So far I understand the problem is that I updated the model but these changes don't apply to database table...kindly help me to fix it..means model properties and database column don't match
Migration is enabled.
I set automatic migration to true but i doesn't work.
Error
public class Floor
{
public int FloorID { get; set; }
public string Name { get; set; }
public virtual ICollection<Room> Rooms { get; set;}
}
public class Room
{
public int RoomID { get; set; }
public string Name { get; set; }
[Display(Name ="Room Rent")]
public decimal Rent { get; set; }
[Display(Name="Floor")]
public int FloorID { get; set; }
public int Seater { get; set; }
[Display(Name="Attach Bathroom")]
public Boolean AttachedBathRoom { get; set; }
public virtual Floor Floor { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
public int CNIC { get; set; }
public int Phone { get; set; }
[Display(Name="Floor")]
public int FloorID { get; set; }
[Display(Name ="Room No")]
public int RoomID { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Department { get; set; }
public virtual Floor Floor { get; set; }
public virtual Room Room { get; set; }
}
First, you need to specify your primary and foreign keys in your classes.
To specify a primary key, add [Key] before your key attribute. For a foreign key, you also have to add the table it is linked to. So in your Room class you would have something like this:
[Key]
[ForeignKey("Floor")]
public int FloorID { get; set; }
Do the same for all your keys in all your models.
Then, you need to add a new migration and then update your database.
In your Packet Manager Console, type this to add a new migration:
Add-Migration FooBar
Then update your database with this command:
Update-Database
Ok so I'm adding on to the Simplemembership.
Model UsersProfiles
namespace OilNGasWeb.Models
{
[Table("Users")]
public class UserProfiles
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Initials { get; set; }
public string Company { get; set; }
public string Department { get; set; }
public string Title { get; set; }
public string Team { get; set; }
public string TeamSub { get; set; }
public string Phone { get; set; }
public string ImageLocation { get; set; }
public string CurrentlyAuthorized { get; set; }
public string Note { get; set; }
public string Comment { get; set; }
//public virtual dbClient Client { get; set; }
public virtual ICollection<Roles> Roles { get; set; } //many to many
public virtual ICollection<dbClient> Clients { get; set; } // many to many
}
}
Roles
namespace OilNGasWeb.Models
{
[Table("webpages_Roles")]
public class Roles
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
[Required(ErrorMessage = "Required")]
public int RoleID { get; set; }
[Required(ErrorMessage = "Required")]
public string RoleName { get; set; }
public virtual ICollection<UserProfiles> UserProfiles { get; set; } //many to many
}
}
My issue now that i have it creating the many to many tables like i saw it creat before modifications my question is how to get those tables Renamed
webpages_UsersInRoles
I would prefer not to go into SSMS and change them physically rather tell MVC to use a different instance
From the code above EF produced RolesUserProfiles instead of webpages_UsersInRoles
The error shows when the program is trying to #if (User.IsInRole("Administrator")) validade user.
Naturally I hit F12 on IsInRole to bring me to the definition....
it does but there all empty
Now what ? how can i recode if its hidden from me ? where is the code at , and how can i Modify this?
What i would like out of all this is
either renaming the tables ManytoMany as they are being created
being able to modify the code that looks for webpages_UsersInRoles
Thanks in advance.
You cannot rename the tables. The table names are hard coded in SimpleMembership. You can see the source code here:
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/WebMatrix.WebData/SimpleMembershipProvider.cs
Don't use the EF navigational properties. You should be accessing this information via the Membership or WebSecurity API's.
If you really want to do this, then you will need to configure EF to use the tablenames required by simple membership, which means utilizing the fluent mapping syntax.. which is not exactly intuitive.
I've created a standard MVC 4 application using the built in account controllers/models/views. I've now tried to add another controller but I want to create a foreign key relationship to an existing user, but im getting the error message:
The ForeignKeyAttribute on property 'CreatedBy' on type 'MVC4App.Models.ListingModel' is not valid. The foreign key name 'UserId' was not found on the dependent type 'MVC4App.Models.ListingModel'. The Name value should be a comma separated list of foreign key property names.
The Listing Model Code is:
using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace MVC4App.Models
{
public class ListingModel
{
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Location { get; set; }
public string Instrument { get; set; }
public string Genres { get; set; }
public string Description { get; set; }
[ForeignKey("UserId")]
public virtual UserProfile CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
}
}
What am I missing here? Or is there a better way I should be doing this?
Also I'm assuming I can just add extra properties to the user profile such as an email address or a link to an avatar image later on in the project?
You have to add the UserId to your entity:
namespace MVC4App.Models
{
public class ListingModel
{
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Location { get; set; }
public string Instrument { get; set; }
public string Genres { get; set; }
public string Description { get; set; }
public int UserId {get; set;}
[ForeignKey("UserId")]
public virtual UserProfile CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
}
}
I have a Project entity and an Rfi entity. The project entity contains a list of TeamMembers. Project is a navigation property in the Rfi entity. In the Rfi entity there is a RecipientId. This Id represents a person from the TeamMembers collection. So imagine, on a web page, we have a drop down box named Recipient. The list includes all team members of the Project. The user will select a Contact from that list. The Id of that contact will be saved in the RecipientsId property. When the page is reloaded we will select the Id of that user in the drop down based off the value in the RecipeintsId property. What is the best way to map this in EF 4.1 using the fluent API?
public class Project : BaseEntity
{
public string ProjectNumber { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string Currency { get; set; }
#region Navigation Properties
public Guid AddressId { get; set; }
public virtual Address Address { get; set; }
public Guid CompanyCodeId { get; set; }
public virtual CompanyCode CompanyCode { get; set; }
public virtual ICollection<Contact> TeamMembers { get; set; }
#endregion
}
public class Rfi : Document
{
public string Number { get; set; }
public string Subject { get; set; }
public string SubcontractorRfiReference { get; set; }
public string SpecificationSection { get; set; }
public RfiStatus RfiStatus { get; set; }
public Guid RecipientId { get; set; }
#region Navigation Properties
public Guid ProjectId { get; set; }
public Project Project { get; set; }
#endregion
}
As I understand it your problem is mapping between Rfi and Contect - Project doesn't have any role in your Recipient functionality from the database perspective.
You need either Recipient navigation property in Rfi or Rfis navigation property in Contact. EF code first needs navigation property on at least one side of the relation.
So you can use something like:
public class Rfi : Document
{
public string Number { get; set; }
public string Subject { get; set; }
public string SubcontractorRfiReference { get; set; }
public string SpecificationSection { get; set; }
public RfiStatus RfiStatus { get; set; }
#region Navigation Properties
public Guid RecipientId { get; set; }
public Contact Recipient { get; set; }
public Guid ProjectId { get; set; }
public Project Project { get; set; }
#endregion
}
And map:
modelBuilder.Entity<Rfi>()
.HasRequired(r => r.Recipient)
.WithMany()
.HasForeignKey(r => r.RecipientId);