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; }
}
}
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 am trying to define a database model in code-first to see and display which user is assigned as a specialist for the record data.
I have a very simple model for the user:
public class User
{
public int ID { get; set; }
public string userName { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
....
}
Next I have defined two (simple) models which define the data that can be edited by the user and the specialist should be assigned to using a dropdownlist:
public class Order
{
public int ID { get; set; }
public string orderNumber { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
public class Part
{
public int ID { get; set; }
public string partNumber { get; set; }
public string description { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
What kind of relation between the models can be used without having a navigation property for each table in the User model?
Do I need to use additional tables to define the relationship: User.Id-Order.specialistID and the relationship: User.Id-Part.specialistID ?
Is there a smarter way out-of-the-box by Entity Framework?
Many thanks for your answers.
Pascal
By default when you add forign-key constraint to the many-to-one table the Entity Framework add virtual property to the entity class and virtual ICollection to the User.
Question 1.
I have created a database in code-first.
[Column(TypeName="datetime2")]
public DateTime RegistDate { get; set; }
In this way, the table is not created.
modelBuilder.Entity<Test>().Property(f => f.RegistDate).HasColumnType("datetime2");
(In OnModelCreating method)
I can be resolved by using Fluent API.
To create a column format datetime2, is there a way only a Fluent API?
Question 2.
I have a domain model as follows.
User Entity Class
public class User
{
public Guid UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string UserEmail { get; set; }
public DateTime JoinDate { get; set; }
public DateTime LoginDate { get; set; }
public virtual ICollection<UsersInRole> UsersInRoles { get; set; }
}
Role Entity Class
public class Role
{
public Guid RoleId { get; set; }
public string RoleName { get; set; }
public DateTime CreateDate { get; set; }
public virtual ICollection<UsersInRole> UsersInRoles { get; set; }
}
UsersInRole Entity Class
public class UsersInRole
{
public Guid UserId { get; set; }
public Guid RoleId { get; set; }
public DateTime SetDate { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
[ForeignKey("RoleId")]
public Role Role { get; set; }
}
This build, the following error will occur
One or more validation errors were detected during model generation:
\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'UsersInRole' has no key defined. Define the key for this EntityType.
\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'UsersInRoles' is based on type 'UsersInRole' that has no keys defined.
I do not want to add another property Id.
Also, I can not use the [Key] UserId, to RoleId.
There are no other solutions?
I am a MVC newbie so go easy on me please.
I am getting two errors when I try to add a migration. They are as follows:
EntityType 'Icon' has no key defined. Define the key for this EntityType.
EntityType: EntitySet 'Icons' is based on type 'Icon' that has no keys defined.
I am including the Icon inside another model, like so:
public class Icon
{
public string IconName { get; set; }
public string IconColor { get; set; }
public int BackgroundXPos { get; set; }
public int BackgroundYPos { get; set; }
public string IconColorHover { get; set; }
public int BackgroundHoverXPos { get; set; }
public int BackgroundHoverYPos { get; set; }
}
public class GalleryThumbnail : CSSBoxModel
{
[DisplayName("Thumbnail Image Outline Color")]
public string ThumbnailImageOutlineColor { get; set; }
[DisplayName("Thumbnail Menu Font")]
public CSSFont ThumbnailMenuFont { get; set; }
[DisplayName("Thumbnail Icon Color")]
public Icon ThumbnailIconColor { get; set; }
}
How is this Address class below any different which is working:
public class Address
{
public String Adress1 { get; set; }
public String Adress2 { get; set; }
public String Adress3 { get; set; }
public String City { get; set; }
public String County { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public String Country { get; set; }
}
[Table("UserProfile")] //Could be PP empolyee, Subscriber or Subscriber's customer
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public bool? Gender { get; set; }
public Address Address { get; set; } //billing address
public Address ShipAddress { get; set; }
}
I did not add a key in either my Icon or Address class because I have no intention of storing specific data in my DB. They are merely to be used inside other classes. So wy is one neededing an ID and the other is not?
I have not created public DbSet Icons { get; set; } in my DB Context either.
Also can you tell me what it is called when you use a class inside another ( or instance of class inside a class as in these examples ) ?
Much appreciated!
Since the address entity has no key defined it the Entity Framework assumes it's a complex property, and your UserProfile table will be rendered with columns named Addres_Address1, Address_Address2, Address_Address3, Address_City, and so on...
Even though you haven't declared an EntitySetIcons DbSet on your context class, it's still being added implicitly because one of your other classes somewhere has an ICollection or IEnumerable property defined.
More info on Code Conventions here:
http://msdn.microsoft.com/en-us/data/jj679962.aspx
So, either decorate the collections as NotMapped like #Kamyar said or simply remove the references from any class already declared as a DbSet.
you can use [NotMapped] attribute in System.ComponentModel.DataAnnotations.Schema namespace in EntityFramework.dll:
using System.ComponentModel.DataAnnotations.Schema;
...
[NotMapped]
public Address Address { get; set; } //billing address
[NotMapped]
public Address ShipAddress { get; set; }
Regarding the naming, AFAIK these are called public properties as well.
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);