Invalid Column Name with EF - entity-framework

I modified the table UserProfile in the database with some extra columns and then modified the UserProfile class to reflect them:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
public string School { get; set; }
}
Obviously they are FirstName, Surname and School. For some reason though despite the register action saving details into all 3 of these new columns when I try to load the data via:
var context = new UsersContext();
var user = context.UserProfiles.First(n => n.UserName == model.UserName);
It says that School is an invalid ColumnName. I checked it was a string in both class and table so bit confused how to debug, help!

(Continued from comments on OP)
Rather than doing this manually, you should consider using the EF migrations framework - There are a number of benefits and it's more future-proof in case internal EF functionality changes.
See here for more information on migrations

Related

EF creating an unwanted field in database

I've hit a snag while building a .net mvc site. I have 2 related objects and am struggling with properly linking them. Specifically:
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostCode { get; set; }
[ForeignKey("AddressCategory")] // <-- EF adds field to below object's table
public int AddressCategoryId { get; set; }
public virtual AddressCategory AddressCategory { get; set; }
}
public class AddressCategory
{
public int AddressCategoryId { get; set; }
public string Description { get; set; }
}
Adding the [ForeignKey] data annotation to the Address object results in EF adding an Address_AddressId column to the AddressCategory table, which I don't want (or need) to happen.
I've tried to omit the ForeignKey attribute, but then I run into other errors because .net can't link the tables (e.g. Unknown column 'Extent1.AddressId' in 'field list'). Additionally, I wouldn't be able to use:
var addresses = db.Addresses.Include(l => l.AddressCategory);
Is there any way to link the 2 tables without EF adding an additional column to the AddressCategory table?
Thank you to #cloudikka for responding. After much trial-and-error I seem to have gotten it to work simply by omitting any ForeignKey reference from either object. I let EF rebuild the database and perform all scaffolding (CRUD forms) and they have been created perfectly.
My take-away is that foreign key attributes should be used for parent-child relationships, but not for look-up tables. I clearly have much to learn about asp.net mvc!

How to map multiple tables into one Entity in EF7

I have 2 tables in different schemas:
Base.Person
ID
FirstName
LastName
Enrollment.Student
PersonID
StudentNo
This is related one-to-one.
Now in my DbContext, I want to have a DbSet named Students but I want its properties mapped to Person and Students. In particular, I want to get Person.ID, Person.FirstName, Person.LastName, Student.StudentNo mapped into my Student class.
The Student class is:
public class Student
{
public int ID { get; set;}
public string FirstName { get; set;}
public string MiddleName { get; set;}
public string StudentNo { get; set;}
}
One additional question that I'd like to ask which is not related to my problem above but it will be clearer to ask if the example above is present, in designing your DbContext, is DbContext intended to make the whole of the database available to you or is it ok just to expose what you want? For example, in my question above, I don't have a Person DbSet.
You cannot currently do this in EF 7 EF Core. However, you can model one to one relationships like this:
[Table("Student", Schema = "Enrollment")]
public class Student
{
[Key]
public string StudentNo { get; set; }
[ForeignKey("PersonId")]
public Person Person { get; set; }
[Column("PersonID")] // <-- if your db is case sensitive
public int PersonId { get; set; }
}
[Table("Person", Schema="Base")]
public class Person
{
// [Key] - not needed as EF conventions will set this as the "key"
[Column("ID")] // again, if case sensitive
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
// in code, use .Include to materialize dependent entities like so....
context.Students.Include(s => s.Person).Where(s => s.Person.FirstName == "Bob");
For more info on modeling, see https://docs.efproject.net/en/latest/modeling/relationships.html#one-to-one

How can I update a Code First application to accommodate manual schema changes?

I have an app that was created using EF. The problem is that I noticed some extraneous foreign keys columns created in one of the tables. Dropping these columns causes an [SqlException (0x80131904): Invalid column name 'Material_Id' error.
Here is a simplified version of the class structure...
public class Hazard
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class HazardAnalysis
{
public int Id { get; set; }
public int HazardId { get; set; }
public virtual Hazard Hazard { get; set; }
}
public class ProductHazard : HazardAnalysis
{
public int ProductId { get; set; }
public virtual Product Product { get; set; }
}
The table that was generated looked like this...
dbo.Hazards
Id int
Name string
Product_Id int
Since the relationship between ProductHazards and Hazards is 1:many, the Product_Id field should not be there. Dropping this column generates the Invalid column name 'Product_Id' error.
I've scoured the model for hours and can't find any valid reason for this column to exist.
Is there any way to update the model after manually dropping a column? I obviously don't want to drop and recreate the database.
I've also noticed that the productId of the current product is inserted in the dbo.Hazards Product_Id table whenever a new ProductHazard is created. Since there is a many-to-one relationship between ProductHazards and Hazards, when a new ProductHazard is created, the Product_Id field is updated with the ProductId of the new ProductHazard, which seems bizarre.
Any advice would be greatly appreciated.
Here is the DbSet code:
public DbSet<Hazard> Hazards { get; set; }
public DbSet<HazardAnalysis> HazardAnalyses { get; set; }
and also...
modelBuilder.Entity<HazardAnalysis>()
.HasRequired(e => e.Hazard)
.WithMany()
.HasForeignKey(e => e.HazardId)
.WillCascadeOnDelete(false);
You need to define the many part of the relationship. In this case, you need to add a collection property to your Hazard object, like below:
public class Hazard
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HazardAnalysis> HazardAnalyses { get; set; }
}

Do all associated objects have to be accessed (lazyloaded) before an existing object can be saved?

I'm learning EF Code First and am having trouble when updating existing records. I've boiled it down to this simple example:
This works:
using(var db = new DataContext()){
var p = db.People.Find(1);
p.Name="New Name";
Console.WriteLine(p.Gender.Name); //<--Unnecessary property access
db.SaveChanges(); //Success
}
...but this fails (when the WriteLine is removed):
using(var db = new DataContext()){
var p = db.People.Find(1);
p.Name="New Name";
db.SaveChanges(); //DbValidationError "Gender field is required."
}
Why do I have to access/load the Gender propery if I'm not using it and the data is already correctly stored in the database? I just want to change the Name on an existing record. In this example, Gender is a one-to-many association stored as Gender_Id in the People table. The classes are defined like this:
public class Person
{
[Key]
public int PersonId { get; set; }
[Required, MaxLength(50)]
public string Name { get; set; }
[Required, Column("Gender")]
virtual public GenderCode Gender { get; set; }
}
public class GenderCode
{
[Key]
public int Id { get; set; }
[Required, MaxLength(10)]
public string Name { get; set; }
}
public class DataContext:DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<GenderCode> GenderCodes { get; set; }
}
Of course, the fully defined classes are to have many more fields. I'd rather not have to access every dependant property every time I want to modify an unrelated value.
Is there a way to load an object, change a field, and save it without loading all related objects first?
Yes, this is necessary because of some horrible design mistakes in EF.
Check out my similar question, EF: Validation failing on update when using lazy-loaded, required properties
One trick is declaring FK properties along with the OO relations:
[ForeignKey("GenderId"), Column("Gender")]
virtual public GenderCode Gender { get; set; }
[Required]
public int GenderId { get; set; }
It is because you are using data annotations and Required attribute has also meaning for validation. Once you set navigation property as Required by data annotation it must be filled / loaded when you are going to persist entity to the database.

EF CTP4 Missing columns in generated table

I'm having an issue that i just can't seem to figure out. Lets say I have 2 Entities defined in my domain; Person and Document. Below is the definition for Document :
public class Document
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Title { get; set; }
public DateTime Date { get; set; }
public virtual Person Owner{ get; set; }
public virtual Person AssignedTo { get; set; }
}
Now, when EF CTP4 creates the SQL table on initialize, there is only one field mapping to a Person.Id being Owner_id. Whatever i try, the field for AssignedTo is never created.
Anything that could solve this?
Regards,
avsomeren
Your code perfectly created the desired schema in the database for me:
If you don't get this schema in you DB then my guess is that something is not right with the rest of your object model. Could you post your full object model please?
Another Solution:
While your current Document class will give you the desired results, but you can still take advantage of the Conventions for Code First and explicitly specify the FKs for your navigation properties:
public class Document
{
public int Id { get; set; }
[Required][StringLength(255)]
public string Title { get; set; }
public DateTime Date { get; set; }
public int OwnerID { get; set; }
public int AssignedToID { get; set; }
public virtual Person Owner { get; set; }
public virtual Person AssignedTo { get; set; }
}
Code First will now infer that any property named <navigation property name><primary key property name> (e.g. OwnerID), with the same data type as the primary key (int), represents a foreign key for the relationship.
This essentially results to the same DB schema plus you have the FKs on your Document object as well as navigation properties which gives you ultimate flexibility to work with your model.