I'm using EF code first migrations in MVC5 with SQL Server.
I created a post method, I'm posting DTO data from the client and its all fine i believe, but when i try to save the data to the db i get this invalid column name exception on a foreign key property.
This is the first time i actually counter this error. I checked other questions and most answers were related to the [ForeignKey] data annotation but i think i implemented it the right way
This is the Model
public class ServiceProvider
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public double YearsOfExperiance { get; set; }
public double AverageRank { get; set; }
public string Nationality { get; set; }
public ICollection<JobImage> JobImages { get; set; }
public ICollection<Review> Reviews { get; set; }
public ICollection<Rank> Ranks { get; set; }
public bool Active { get; set; }
[ForeignKey("Category")]
public int CategoryId { get; set; }
public Category Category { get; set; }
public bool Approved { get; set; }
}
This is the controller ActionResult method
[HttpPost]
public ActionResult AddServiceProvider(ServiceProviderDTO serviceProvider)
{
bool isInDb = _context.ServiceProviders.Any(s => s.Name == serviceProvider.Name) ? true : false;
//var serviceProviderInDb = _context.ServiceProviders.Where(s => s.Name == serviceProvider.Name).FirstOrDefault();
var newServiceProvider = new ServiceProvider();
if (isInDb == false)
{
newServiceProvider = new ServiceProvider
{
Id = Guid.NewGuid(),
Name = serviceProvider.Name,
PhoneNumber = serviceProvider.PhoneNumber,
YearsOfExperiance = serviceProvider.YearsOfExperiance,
Nationality = serviceProvider.Nationality,
CategoryId = serviceProvider.CategoryId,
Active = true,
Approved = serviceProvider.Approved == null ? false : serviceProvider.Approved.Value
};
_context.ServiceProviders.Add(newServiceProvider);
_context.SaveChanges();
}
return RedirectToAction("Index", "Home");
}
The error occurs on _context.SaveChanges();
It states that CategoryId is an invalid column name
This is not the first time that i use code first migrations and i never came across this error before so i really have no idea why this happens!
I would have the model like this.
The ForeignKey attribute belong to the Category property
public class ServiceProvider
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public double YearsOfExperiance { get; set; }
public double AverageRank { get; set; }
public string Nationality { get; set; }
public ICollection<JobImage> JobImages { get; set; }
public ICollection<Review> Reviews { get; set; }
public ICollection<Rank> Ranks { get; set; }
public bool Active { get; set; }
public int CategoryId { get; set; }
[ForeignKey("CategoryId")]
public Category Category { get; set; }
public bool Approved { get; set; }
}
you need delete this property public int CategoryId { get; set; }
your property public Category Category { get; set; } is the ForeignKey and add the DataAnnotations [ForeignKey("CategoryId")]
it would look like this
public class ServiceProvider
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public double YearsOfExperiance { get; set; }
public double AverageRank { get; set; }
public string Nationality { get; set; }
public ICollection<JobImage> JobImages { get; set; }
public ICollection<Review> Reviews { get; set; }
public ICollection<Rank> Ranks { get; set; }
public bool Active { get; set; }
[ForeignKey("Category")]
public int CategoryId { get; set; }
public Category Category { get; set; }
public bool Approved { get; set; }
}
Related
My Club has many members so I have added the following virtual property Members my question is when I want to list the club members shouldn't adding just the virtual load this into lazy loading am using .net 5.0.1 at present.
var members = _context.Clubs.Include(c=>c.Members).Where(w => w.ClubId == tennantId ).ToList();
When I look at var members even when the members have been included it is zero even though the teannatId matches.
public class MSFSAddonDBContext : IdentityDbContext<ApplicationUser>
{
public MSFSAddonDBContext(DbContextOptions<MSFSAddonDBContext> options)
: base(options)
{
}
public DbSet<Club> Clubs { get; set; }
public virtual List<ApplicationUser>? Members { get; set; }
}
This is my controller method.
public void IActionResult ClubMembers()
{
var tennantId = GetTennantId().Result;
var members = _context.Clubs.Include(c=>c.Members).Where(w => w.ClubId == tennantId ).ToList();
return View(members);
}
There are two members references at top level and inside the clubs.
This is the club class
public class Club
{
public int Id { get; set; }
public Guid? TeannatId { get; set; }
public Guid? ClubId { get; set; }
public Guid? UserId { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public string? Url { get; set; }
public int? ClubLikes { get; set; }
public int? ClubDislikes { get; set; }
public int? MembersCount { get; set; }
public string? Logo { get; set; }
public List<Flight>? Flights { get; set; }
public string? ThumbNail { get; set; }
public DateTimeOffset? GpdrRemoveRequestDate { get; set; }
public bool? isGpdrRemoveRequest { get; set; }
public DateTimeOffset? BannedTime { get; set; }
public TimeSpan? BanPeriod { get; set; }
public bool? isBanned { get; set; }
public bool? isActive { get; set; }
public bool? isDeleted { get; set; }
public DateTime? CreatedDate { get; set; }
public string? CreatedBy { get; set; }
public virtual List<ApplicationUser>? Members { get; set; }
}
Edit 2
This is the application user class.
public class ApplicationUser : IdentityUser
{
public enum UserTypeEnum
{
Guest=0,
User=1,
Author=2,
AddonOwner=3,
GroupOwner=5,
ClubMember=6,
ClubAdmin=7,
SuperAdmin=199,
BandUser=999
}
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? GamerTag { get; set; }
public bool? isOnline { get; set; }
public int? UserType { get; set; }
public Guid? TennantId { get; set; }
public Guid? ClubId { get; set; }
public List<Badges>? Badges { get; set; }
}
NB As always with ef the primary keys in all my tables are the Id column thanks
I have two table like this -
public class Job
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime AddedTime { get; set; } = DateTime.Now;
public DateTime LastEdit { get; set; } = DateTime.Now;
public string Explanation { get; set; }
public string PhotoString { get; set; }
public bool isActive { get; set; } = true;
public int CompanyId { get; set; }
public Company Company { get; set; }
}
and company -
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Explanation { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string PhotoString { get; set; }
public bool isActive { get; set; } = true;
public int AppUserId { get; set; }
public AppUser AppUser { get; set; }
public List<Job> Jobs { get; set; }
}
I only want to get AppUserId from Company and all Jobs from every Company. I tried this and it gave me error.
using var context = new SocialWorldDbContext();
return await context.Jobs.Where(I => I.isActive == true && I.Company.isActive).Include(I=>I.Company.AppUserId).ToListAsync();
So my question is there any way I can get this data from parent?
Include adds whole entities to the output. To add just one property use Select, something like
context.Jobs
.Where(I => I.isActive == true && I.Company.isActive)
.Select(e => new {Job=e, CompanyAppUserId = e.Company.AppUserId})
.ToListAsync();
public IEnumerable<Parties> GetAll()
{
return database.Parties;
}
Works very well and the output is:
But when I Include another table by foreignkey like this:
public IEnumerable<Parties> GetAll()
{
return database.Parties.Include(i=>i.User);
}
It does not work, it returns first value of the table and nothing else,the output is :
Users.cs :
public partial class Users
{
public Users()
{
Parties = new HashSet<Parties>();
PartyParticipants = new HashSet<PartyParticipants>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public string Avatar { get; set; }
public string Biography { get; set; }
public string Password { get; set; }
public virtual ICollection<Parties> Parties { get; set; }
public virtual ICollection<PartyParticipants> PartyParticipants { get; set; }
}
Parties.cs :
public partial class Parties
{
public Parties()
{
Image = new HashSet<Image>();
PartyParticipants = new HashSet<PartyParticipants>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime PartyDate { get; set; }
public DateTime CreatedDate { get; set; }
public int ParticipantCount { get; set; }
public int MaxParticipant { get; set; }
public string PartySplash { get; set; }
public string ShortDescription { get; set; }
public string Description { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public bool EntranceFree { get; set; }
public int? FreeParticipant { get; set; }
public int? FreeParticipantMax { get; set; }
public int UserId { get; set; }
public virtual Users User { get; set; }
public virtual ICollection<Image> Image { get; set; }
public virtual ICollection<PartyParticipants> PartyParticipants { get; set; }
}
As you can see on the 2nd picture it interrupts at first row of the table.
I have added this answer based on Vidmantas's comment. ReferenceLoopHandling should be ignored like this in startup.cs:
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
I have a statement in one of my entities which uses a foreign key to return an IEnumerable<CustomField>.
I have used LINQ in my repository to test the below method to see if it works and it does. But when I use the foreign key reference in the entity it returns null. Am I missing something here? How can I use a foreign key to gain access to the data in another entity.
Invoice entity:
[Table("vwinvoice")]
public class Invoice
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Sys_InvoiceID { get; set; }
[DisplayName("Inc.In Turnover")]
public bool Turnover { get; set; }
public int FK_StatusID { get; set; }
[DisplayName("Invoice No.")]
public string InvoiceNumber { get; set; }
[DisplayName("Invoice Date")]
public DateTime InvoiceDate { get; set; }
[DisplayName("Document Type")]
public string DocType { get; set; }
[DisplayName("Supplier Invoice No.")]
[Column("SupplierInvoiceNumber")]
public string SuppInvNumber { get; set; }
public int FK_SupplierID { get; set; }
[DisplayName("Account Number")]
public string AccountNumber { get; set; }
[DisplayName("Order Number")]
public string OrderNumber { get; set; }
[DisplayName("Order Date")]
public DateTime? OrderDate { get; set; }
[DisplayName("Currency Code_Doc")]
public string CurrencyCode_Doc { get; set; }
[DisplayName("Net Amount_Doc")]
public decimal? NetAmount_Doc { get; set; }
[DisplayName("VAT Amount_Doc")]
public decimal? VATAmount_Doc { get; set; }
[DisplayName("Gross Amount_Doc")]
[Required]
public decimal? GrossAmount_Doc { get; set; }
[DisplayName("Currency Code_Home")]
public string CurrencyCode_Home { get; set; }
[DisplayName("Net Amount_Home")]
public decimal? NetAmount_Home { get; set; }
[DisplayName("VAT Amount_Home")]
public decimal? VATAmount_Home { get; set; }
[DisplayName("Gross Amount_Home")]
public decimal? GrossAmount_Home { get; set; }
[DisplayName("Payment Reference")]
public string PaymentReference { get; set; }
[DisplayName("Supplier")]
public string AccountName { get; set; }
[DisplayName("Status")]
public string StatusName { get; set; }
[DisplayName("Auditor Comments")]
public string AuditorComments { get; set; }
[DisplayName("Reviewer Comments")]
public string ReviewerComments { get; set; }
[DisplayName("Data Source")]
[Required]
public string DataOrigin { get; set; }
public int DetailLineCount { get; set; }
public IEnumerable<CustomField> ClientData {
get {
//Use the CustomFields foreign key to gain access to the data returns null.
return GetCustomFieldData(this.CustomFields.Select(r => r));
}
}
private IEnumerable<CustomField> GetCustomFieldData(IEnumerable<Entities.CustomFields> enumerable) {
return (from f in enumerable
select new CustomField {
Name = f.FK_CustomHeader,
Value = f.Value
});
}
//Custom Field Additions
public virtual ICollection<CustomFields> CustomFields { get; set; }
}
CustomFields entity:
[Table("tblCustomFields")]
public class CustomFields
{
[Key]
public int ID { get; set; }
public int? FK_SysInvoiceID { get; set; }
[StringLength(255)]
public string FK_CustomHeader { get; set; }
[StringLength(255)]
public string Value { get; set; }
public virtual Invoice Invoices { get; set; }
public virtual CustomFieldHeaders CustomFieldHeaders { get; set; }
}
I also cannot place a breakpoint in the get statement to see what happens, why is this? It just skips over the breakpoint whenever I try to return a list of Invoices, which can be seen here:
public IQueryable<Invoice> Invoices
{
get
{
var x = _ctx.Invoices.ToList();
return _ctx.Invoices;
}
}
You are using the virtual keyword when declaring your CustomFields property. As such it will be lazy loaded. If you want the property to be populated once returned from the repository you will need to explicitly Include the table in your method:
var x = _ctx.Invoices.Include(i => i.CustomFields).ToList();
return _ctx.Invoices;
Or you can remove the virtual keyword and the property will always be populated, with the consequent performance hit of the database join and the extra data being returned whenever you access Invoices.
Hi guys I am spinning wheels on this one. I am using EF6 and ASP.Net 4.6. I have a given table which has student information and parent information. A student can have many parents and a parent can have many students. Call this table 'Contact'. I am to create a table called 'Request' which will hold information for a parent submitting a request for his student. I will create a lookup table with two columns, one for student id and one for parent id called 'StudentParents'. I want to be able to have the parent log in, select his student from a drop down of all of his students and submit the request. The many to many relationship is throwing me off as far as my include statements. How can I get EF to set up this structure so that when I GetRequest(id) I can get the Student info and the Parent info to be included? Here is my code that wont Include anything other than the request.
public class Contact
{
[Key]
public int id { get; set; }
public string student_id { get; set; }//This is the Student ID
public string last_name { get; set; }
public string first_name { get; set; }
public string middle_initial { get; set; }
public string grade { get; set; }
public int current_school_id { get; set; }
public string current_school_name { get; set; }
[Display(Name = "Parent Last Name")]
public string contact_first_name { get; set; }
[Display(Name = "Parent Middle Name")]
public string contact_middle_name { get; set; }
[Display(Name = "Parent Last Name")]
public string contact_last_name { get; set; }
public string contact_relationship { get; set; }
[Display(Name = "Parent Email")]
public string contact_email { get; set; }
[Display(Name = "Parent Address")]
public string login { get; set; }//This is the Parent ID
public string Classif_description { get; set; }
}
public class Request
{
[Key]
public int id { get; set; }
public Student student_id { get; set; }
public Contact login { get; set; }
[Display(Name = "First School Choice")]
public string firstSchool { get; set; }
[Display(Name = "Second School Choice")]
public string secSchool { get; set; }
[Display(Name = "Rising Grade")]
public string rising_grade { get; set; }
public DateTime ReqSubmitted { get; set; }
public string ReqStatus { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public string ModifBy { get; set; }
}
public class Parent
{
public int id { get; set; }
public string contact_first_name { get; set; }
public string contact_middle_name { get; set; }
public string contact_last_name { get; set; }
public string contact_relationship { get; set; }
public string contact_email { get; set; }
public string contact_address { get; set; }
public string contact_city { get; set; }
public string contact_zip { get; set; }
[Key]
public string login { get; set; }
public string contact_pw { get; set; }
public string phone { get; set; }
public string phone_type { get; set; }
public Parent() { }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
[Key]
public int id { get; set; }
public int student_id { get; set; }
public string last_name { get; set; }
public string first_name { get; set; }
public string middle_initial { get; set; }
public DateTime birthdate { get; set; }
public string gender { get; set; }
public string grade { get; set; }
public string Fed_race_description { get; set; }
public string Classif_description { get; set; }
public int current_school_id { get; set; }
public string current_school_name { get; set; }
public int home_school_id { get; set; }
public string home_school_name { get; set; }
public Student()
{
this.Parents = new HashSet<Parent>();
}
public virtual ICollection<Parent> Parents { get; set; }
}
public class OEContext : DbContext
{
public OEContext() : base("name=OEContext")
{
}
public DbSet<Request> Requests { get; set; }
public DbSet<Parent> Parents { get; set; }
public DbSet<Contact> Contacts { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>()
.HasMany(s => s.Students)
.WithMany()
.Map(x =>
{
x.MapLeftKey("login");
x.MapRightKey("student_id");
x.ToTable("StudentParents");
}
);
base.OnModelCreating(modelBuilder);
}
}
Changed the strategy. Made Request have many Contacts. So I added a constructor to the request:
public Request()
{
Contacts = new List<Contact>();
}
public virtual ICollection<Contact> Contacts { get; set; }
Next I changed the contact class:
public int ContactId { get; set; }
public Contact() { }
public virtual Request Request { get; set; }
With this relationship I can pull both Parents and a student from the Contacts associated with the Request.