public partial class User {
public int Id { get; set; }
public Nullable<int> InvoiceAddress_Id { get; set; }
public Nullable<int> MailAddress_Id { get; set; }
public virtual Address Address { get; set; }
public virtual Address Address1 { get; set; }
}
When I try to retrieve user using Linq and Entity framework, I get;
Invalid column name 'Address_Id1'.
Invalid column name 'Address1_Id1'.
Invalid column name 'Address_Id'.
Invalid column name 'Address_Id1'.
I have no idea why it's coming up like that and doing search for any of these columns in the solution gives nothing! I have a feeling it has something to do with foreign keys.
public partial class Address
{
public Address()
{
this.User = new HashSet<User>();
this.User1 = new HashSet<User>();
}
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public virtual ICollection<Customer> User { get; set; }
public virtual ICollection<Customer> User1 { get; set; }
}
Here is how I'm using entity framework:
CustomDbContext db = new CustomDbContext ();
var user = db.User.First(a => a.Id != 0);
Here's the updated code:
public partial class User
{
public int Id { get; set; }
public Nullable<int> InvoiceAddress_Id { get; set; }
public Nullable<int> MailAddress_Id { get; set; }
public virtual Address InvoiceAddress_ { get; set; }
public virtual Address MailAddress_ { get; set; }
}
Here's the error:
Invalid column name 'Address_Id'.
Invalid column name 'Address_Id1'.
The problem is quite clear: nor your code (attributes, fluent API), neither the EF conventions are configuring the FKs.
If you want to use conventions, you have to adjust the names of the properties and the foreign keys, so that they can be configured. Where you have:
public Nullable<int> InvoiceAddress_Id { get; set; }
public virtual Address Address { get; set; }
You should have:
public Nullable<int> InvoiceAddressId { get; set; }
public virtual Address InvoiceAddress { get; set; }
Note that the FK name is the navigation property name + "Id"
Other option is to implement OnModelCreating of your DbContext and configure the FKs using the fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOptional(u => u.Address)
.WithMany();
.HasForeingKey(a => a.InvoiceAddres_Id);
}
Or use the [ForeignKey("")] attribute:
The annotation may be placed on the foreign key property and specify the associated navigation property name, or placed on a navigation property and specify the associated foreign key name
I.e.
[ForeignKey("Address")]
public Nullable<int> InvoiceAddress_Id { get; set; }
or
[ForeignKey("InvoiceAddress_Id")]
public virtual Address Address { get; set; }
Related
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
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 am still on my quest to port from a Model First to Code First implementation of EntityFramework. I have made significant progress, with the help of Eranga. I have run into another snag, and I just cant explain what is hapening. I have two Entity objects Topic and Course
A Topic can have one Course that is required
A Course can have 0 or more topics
when i execute the following linq it generates wierd SQL
var topics = from o in db.Topics where o.ParentTopic == null &&
o.Course.Id == c.Id select o;
The SQL generated is
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[ShortDescription] AS [ShortDescription],
[Extent1].[LongDescription] AS [LongDescription],
[Extent1].[Property] AS [Property],
[Extent1].[Difficulty] AS [Difficulty],
[Extent1].[Weight] AS [Weight],
[Extent1].[Course_Id] AS [Course_Id],
[Extent1].[ParentTopic_Id] AS [ParentTopic_Id],
[Extent1].[Course_Id1] AS [Course_Id1]
FROM [dbo].[Topics] AS [Extent1]
WHERE ([Extent1].[ParentTopic_Id] IS NULL) AND ([Extent1].[Course_Id] = #p__linq__0)
Notice that there is an added field called Course_Id1 that is not in my object and not declared as a foreign key. I thought that in OnModelCreating() I had specified the parent child relationship correctly from both sides (I would have thought you only needed to do it from either side), but i cant get EntityFramework not to generate the extra field that obviously does not exist in the database. Remember my database was originally created using a ModelFirst approach.
Can anyone explain where the extra field is comming from????
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Topic
modelBuilder.Entity<Topic>()
.HasRequired(m => m.Course)
.WithMany(m=>m.Topics)
.HasForeignKey(m => m.Course_Id);
modelBuilder.Entity<Topic>()
.HasOptional(m => m.ParentTopic)
.WithMany(m => m.ChildTopics)
.HasForeignKey(m => m.ParentTopic_Id);
//////// lots of code removed for brevity. //////
modelBuilder.Entity<Course>()
.HasMany(m=>m.Topics)
.WithRequired(m => m.Course)
.HasForeignKey(m => m.Course_Id);
}
public partial class Topic
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public string Property { get; set; }
public double? Difficulty { get; set; }
public double? Weight { get; set; }
[JsonIgnore]
public virtual Course Course { get; set; }
public int Course_Id { get; set; }
[JsonIgnore]
public virtual ICollection<Question> Questions { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> ChildTopics { get; set; }
[JsonIgnore]
public virtual Topic ParentTopic { get; set; }
public int? ParentTopic_Id { get; set; }
[JsonIgnore]
public virtual ICollection<RTIQueueEntryData> RTIQueueEntryData { get; set; }
[JsonIgnore]
public virtual ICollection<Intervention> Interventions { get; set; }
[JsonIgnore]
public virtual ICollection<RtiStudentGroup> RtiStudentGroups { get; set; }
}
public partial class Course
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public string Version { get; set; }
public string Year { get; set; }
public string ImportedId { get; set; }
[Required]
public string LocalCourseNumber { get; set; }
[Required]
public string NCESCourseNumber { get; set; }
[Required]
public string StateCourseNumber { get; set; }
public int? Grade { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> PerformanceIndicators { get; set; }
[JsonIgnore]
public virtual Department Department { get; set; }
public int DepartmentId { get; set; }
[JsonIgnore]
public virtual ICollection<StudentGroup> StudentGroups { get; set; }
[JsonIgnore]
public virtual ICollection<CutPointTemplate> CutPointTemplates { get; set; }
[JsonIgnore]
public virtual School School { get; set; }
public int School_Id { get; set; }
[JsonIgnore]
public virtual ICollection<Staff> RTIStaff { get; set; }
[JsonIgnore]
public virtual ICollection<Topic> Topics { get; set; }
}
You have another relationship between Course and Topic created by convention due to this navigation property:
public virtual ICollection<Topic> PerformanceIndicators { get; set; }
EF will put an (invisible, not exposed) end of the relationship into the Topic class. By default the relationship is one-to-many. Hence you get an additional foreign key property in the Topics table (= Course_Id1).
So I created the following related Classes and I'm trying to do Code-First approach. I want the Quote class to reference 3 instances of the User class by 3 different navigable property names, but when I do DBInitializer to populate and create the DB, the Quote table has 6 columns instead of the expected 3 columns, of which 3 are always null. The navigable properties point to those 3 null columns, so whenever I point to Quote.Manager or one of the other 3 properties, it returns null instead of the actual manager. How can I fix this?
Quote Class (I left a little off, but you get the point):
using System.Web;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace QuoteManager.Models
{
public class Quote
{
public int QuoteID { get; set; }
public virtual int StateID { get; set; }
public virtual State State { get; set; }
public virtual int CreatorID { get; set; }
public virtual User Creator { get; set; }
public virtual int AgentID { get; set; }
public virtual User Agent { get; set; }
public virtual int ManagerID { get; set; }
public virtual User Manager { get; set; }
}
}
User class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace QuoteManager.Models
{
public class User
{
public User()
{
this.Quotes = new HashSet<Quote>();
this.CreatedQuotes = new HashSet<Quote>();
this.ManagedQuotes = new HashSet<Quote>();
}
public int UserID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual ICollection<Quote> Quotes { get; set; }
public virtual ICollection<Quote> CreatedQuotes { get; set; }
public virtual ICollection<Quote> ManagedQuotes { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
}
Use the InverseProperty attribute to specify the other property participating in the relationship
public class Quote
{
public int QuoteID { get; set; }
public virtual int StateID { get; set; }
public virtual State State { get; set; }
public virtual int CreatorID { get; set; }
[InverseProperty("CreatedQuotes")]
public virtual User Creator { get; set; }
public virtual int AgentID { get; set; }
public virtual User Agent { get; set; }
public virtual int ManagerID { get; set; }
[InverseProperty("ManagedQuotes")]
public virtual User Manager { get; set; }
}
public class User
{
public User()
{
this.Quotes = new HashSet<Quote>();
this.CreatedQuotes = new HashSet<Quote>();
this.ManagedQuotes = new HashSet<Quote>();
}
public int UserID { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual ICollection<Quote> Quotes { get; set; }
[InverseProperty("Creator")]
public virtual ICollection<Quote> CreatedQuotes { get; set; }
[InverseProperty("Manager")]
public virtual ICollection<Quote> ManagedQuotes { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
Similarly map the other relations.
Add the attribute [ForeignKey("Creator")] to the CreatorID and so on for the other 2 property pairs.
FINAL SOLUTION
Thanks to your reference to InverseProperty I found an amazing article that covers exactly what I wanted to accomplish using fluent API. This article was written in January, but I'm pretty sure CTP5 is now officially part of the MVC 3 and EF core.
Associations in EF Code First CTP5
Okay...I'm going to document what I found to work great! I hate it when people leave partial answers, so here we go.
There is a little redundancy here, but it works. My Quote Class looks like this:
[ForeignKey("Creator")]
public virtual int CreatorID { get; set; }
[InverseProperty("CreatedQuotes")]
public virtual User Creator { get; set; }
[ForeignKey("Agent")]
public virtual int AgentID { get; set; }
[InverseProperty("OwnedQuotes")]
public virtual User Agent { get; set; }
[ForeignKey("Manager")]
public virtual int ManagerID { get; set; }
[InverseProperty("ManagedQuotes")]
public virtual User Manager { get; set; }
Then my User class looks like this:
public virtual ICollection<Quote> CreatedQuotes { get; set; }
public virtual ICollection<Quote> OwnedQuotes { get; set; }
public virtual ICollection<Quote> ManagedQuotes { get; set; }
Finally, my DBContext class looks like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Quote>()
.HasRequired(a => a.Manager)
.WithMany()
.HasForeignKey(u => u.ManagerID);
modelBuilder.Entity<Quote>()
.HasRequired(a => a.Agent)
.WithMany()
.HasForeignKey(u => u.AgentID).WillCascadeOnDelete(false);
modelBuilder.Entity<Quote>()
.HasRequired(a => a.Manager)
.WithMany()
.HasForeignKey(u => u.ManagerID).WillCascadeOnDelete(false);
}
You can see the redundancy in the ForeignKey annotation in the Quote class and the Fluent API mapping in the DbContext class, but it's not hurting anything. I could probably do away with the annotations in the Quote class, but the Fluent API is necessary to set the cascading rule to false to prevent foreign key conflicts.
I have been able to navigate both directions with no problems and exactly as expected.
Thanks for all your help!
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);