Eager Load Entity Framework Navigation Property error - entity-framework

I'm trying to eager load some child entities like so:
_context.Sites.Where(x => x.ID == siteID).Include(s => s.SiteLoggers).FirstOrDefault();
However, the error I am getting is:
A specified Include path is not valid. The EntityType 'MyProject.Dal.EF.Site' does not declare a navigation property with the name 'SiteLoggers'.
What is saying is correct, as MyProject.Dal.EF.Site does not exist, the object exists in MyProject.Domain.Entities.Site
What am I missing??? Thanks!
POCOs:
namespace MyProject.Domain.Entities
{
public class Site
{
public int ID { get; set; }
public int LocationID { get; set; }
public bool Active { get; set; }
public bool Deleted { get; set; }
public string Name { get; set; }
public virtual Location Location { get; set; }
public virtual IEnumerable<SiteLogger> SiteLoggers { get; set; }
}
}
namespace MyProject.Domain.Entities
{
public class SiteLogger
{
public int ID { get; set; }
public int UID { get; set; }
public int SiteID { get; set; }
public string Name { get; set; }
public int LocationID { get; set; }
public bool Active { get; set; }
public bool Deleted { get; set; }
public virtual Site Site { get; set; }
public virtual Location Location { get; set; }
}
}

You need to use ICollection instead of IEnumerable, because EF requires that your navigation properties are defined as ICollection<T>.
public virtual ICollection <SiteLogger> SiteLoggers { get; set; }

Related

DbSet property of type class returns null

I'm creating an API for an app. The DbContext I have trouble with looks like this:
public class SchoolPlannerDbContext : DbContext
{
public SchoolPlannerDbContext(DbContextOptions<SchoolPlannerDbContext> options) : base(options) { }
public DbSet<Activity> Activities { get; set; }
public DbSet<Room> Rooms { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Group> Groups { get; set; }
}
The Activity class is as follows:
public class Activity
{
public int ID { get; set; }
[Required]
public Teacher Teacher { get; set; }
[Required]
public Room Room { get; set; }
[Required]
public Subject Subject { get; set; }
[Required]
public Group Group { get; set; }
[Required]
public int Slot { get; set; }
[Required]
public int Day { get; set; }
}
All the other properties contain an int ID and a string Name.
My controller looks like this:
public class SqlPlannerData : ISchoolPlannerData
{
private readonly SchoolPlannerDbContext db;
public SqlPlannerData(SchoolPlannerDbContext db)
{
this.db = db;
}
public IEnumerable<Activity> GetActivities()
{
return db.Activities;
}
public IEnumerable<Group> GetGroups()
{
return db.Groups;
}
}
GetGroups() works as intended and returns an IEnumerable with properties set correctly.
My problem is that when I'm trying to access db.Activities, the properties of type, say, Teacher (non-basic types like int) are set to null:
Debugger screenshot.
However, there is a row in the database that looks like this. I.e. the columns exist in the database.
What do I do to make GetActivities() return an IEnumerable with correctly set properties?
Some properties are null because of lazy loading you need to include them
return db.Activities
.Include(i => i.Teacher)
.Include(i => i.Room)
.Include(i => i.Subject)
.Include(i => i.Group)
.ToList()
Each propety Id can be configured by EF5+ as shadows. But I usually prefer to add all Ids explicitely. This way I have much less problem when I am using db context in the project. But is is optional and you can leave it as is
public class Activity
{
public int ID { get; set; }
[Required]
public int? TeacherId { get; set; }
[Required]
public int? RoomId { get; set; }
[Required]
public int? SubjectId { get; set; }
[Required]
public int? GroupId { get; set; }
public virtual Teacher Teacher { get; set; }
public virtual Room Room { get; set; }
public virtual Subject Subject { get; set; }
public virtual Group Group { get; set; }
[Required]
public int Slot { get; set; }
[Required]
public int Day { get; set; }
}
and in order to get list activities you have to add ToList() or ToArray() at least
public IEnumerable<Activity> GetActivities()
{
return db.Activities.ToArray();
}
and by the way, you can' t using not nullabe Id as required becaue it is relevant
[Required]
public int TeacherId { get; set; }
since int by default is 0 and it is a valid value and required will not be working

Entity framework relation mapping is not working

print("Hello World !");
I'm a beginner into the .NET world, i'm trying to use entity framework but i have a problem, my relations entities are not loaded, i followed the microsoft documentation but.
Here are my models :
[Table("Path")]
public class Path
{
[Key]
public int PathId { get; set; }
[Required]
public string Title { get; set; }
public List<Image> Images { get; set; }
[Required]
public string Description { get; set; }
[Required]
public float LocationX { get; set; }
[Required]
public float LocationY { get; set; }
[Required]
public string QrCode { get; set; }
public List<Mark> Marks { get; set; }
}
[Table("Mark")]
public class Mark
{
[Key]
public int MarkId { get; set; }
public int Value { get; set; }
public int PathForeignKey { get; set; }
[ForeignKey("PathForeignKey")]
public Path Path { get; set; }
}
[Table("Image")]
public class Image
{
[Key]
public int ImageId { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public int PathForeignKey { get; set; }
[ForeignKey("PathForeignKey")]
public Path Path { get; set; }
[Required]
public string Source { get; set; }
}
For me, everything is ok, i even have the correct entries into my database :
database entries
But my relation dont load when i'm reading database into my controller.
[HttpGet]
public IEnumerable<Path> GetAll()
{
return _context.Paths.ToList();
}
results
I'm sorry, i guess it is probably a stupid beginner error but i dont see what i did wrong. I tried with various database system, with virtual or not ...
Mark your navigation properties as virtual. For example:
[Table("Mark")]
public class Mark
{
[Key]
public int MarkId { get; set; }
public int Value { get; set; }
public int PathForeignKey { get; set; }
[ForeignKey("PathForeignKey")]
public virtual Path Path { get; set; } //Added virtual keyword
}
and a second way to load navigation properties is to use Include while fetching data:
return _context.Marks.Include(x => x.Path).ToList();

EF Core More Navigation properties from two tables

I am trying to create navigation properties for two table.
Here is the code.
public class CourseMaster
{
public int Id { get; set; }
public string Name { get; set; }
public int? TeamLeaderId { get; set; }
[ForeignKey("TeamLeaderId")]
public StudentMaster TeamLeader { get; set; }
public int? GroupLeaderId { get; set; }
[ForeignKey("GroupLeaderId")]
public StudentMaster GroupLeader { get; set; }
public virtual ICollection<StudentMaster> Students { get; set; }
}
public class StudentMaster
{
public int id { get; set; }
public string Name { get; set; }
public int FirstSemCourseId { get; set; }
[ForeignKey("FirstSemCourseId")]
public CourseMaster FirstSemCourse { get; set; }
public int SecondSemCourseId { get; set; }
[ForeignKey("SecondSemCourseId")]
public CourseMaster SecondSemCourse { get; set; }
public int ThirdSemCourseId { get; set; }
[ForeignKey("ThirdSemCourseId")]
public CourseMaster ThirdSemCourse { get; set; }
public int CourseMasterId { get; set; }
public CourseMaster Course { get; set; }
}
// Fluent API
modelBuilder.Entity<StudentMaster>()
.HasOne(p => p.Course)
.WithMany(b => b.Students)
.HasForeignKey(p => p.CourseMasterId);
But when i am creating migrations i am getting following error.
Unable to determine the relationship represented by navigation property 'CourseMaster.TeamLeader' of the type 'StudentMaster'. Either manually configure the relationship, or ignore this property from model.
Whether the procedure i am following is right or should i create intermediate class.
or how should i create class.
Any help are appreciated.
Thanks

EF code first model not in sync with database

My EF Code First model for some reason is not in sync with the db. I'm getting this error:
{"Invalid column name 'Type_Id1'."}
The field is actually called 'Type_Id' so I'm not sure from where that 1 comes up. I have the table column called as Type_Id and also I've added a Type_Id in my type entity model.
Why might I be getting that error message, plus why I'm getting 1 at the end of the name?
Update
My Task class:
public class Task
{
public Task()
{
Language = 1;
Grades = new HashSet<Grade>();
Categories = new HashSet<Category>();
Subjects = new HashSet<Subject>();
Rooms = new Collection<Room>();
Tools = new Collection<Tool>();
}
[Key]
public int Id { get; set; }
public string Description { get; set; }
public virtual TaskType Type { get; set; }
public string Rules { get; set; }
[Required]
[StringLength(200), MinLength(1)]
public string Name { get; set; }
public int PreperationTime { get; set; }
public int InstructionTime { get; set; }
public int TaskTime { get; set; }
public int Type_Id { get; set; }
public string VideoLink { get; set; }
[Required]
public int Language { get; set; }
public int? MinimumParticipants { get; set; }
public int? MaximumParticipants { get; set; }
public int? Rating { get; set; }
[Required]
public string CreatedBy { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
public virtual ICollection<Tool> Tools { get; set; }
}
DBContext class:
public ApplicationDbContext() : base("DefaultConnection", false)
{
}
public DbSet<Task> Tasks { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
You need to add the FK attribute on your navigation property. EF is creating Type_Id1 because Type_Id already exists (although it can't tell by convention it is the FK).
[ForeignKey("Type_Id")]
public virtual TaskType Type { get; set; }
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships

A specified Include path is not valid. Entity Framework Code First

I am getting the following error when trying to run a query in EF.
A specified Include path is not valid. The EntityType 'InvestmentClub' does not declare a navigation property with the name 'ClubMembers'.
Query
return _context.InvestmentClubs.Where(x => x.InvestmentClubId == clubId)
.Include(x => x.Policies).Include(x => x.ClubMembers).FirstOrDefault();
Investmentclub class
public class InvestmentClub
{
public int InvestmentClubId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int CreatedBy { get; set; }
public DateTime DateCreated { get; set; }
public InvestmentClubType ClubType { get; set; }
//Navigation properties
[ForeignKey("CreatedBy")]
public ApplicationUser ApplicationUser { get; set; }
public ICollection<InvestmentClubMember> ClubMembers;
public ICollection<InvestmentClubPolicy> Policies;
}
InvestmentClubPolicy class
public class InvestmentClubPolicy
{
public int InvestmentClubPolicyId { get; set; }
public int InvestmentClubId { get; set; }
public DateTime DateAdded { get; set; }
public string PolicyStatement { get; set; }
public AjoPolicyStatus PolicyStatus { get; set; }
public InvestmentClub InvestmentClub { get; set; }
}
I did not specify the properties as virtual as I didn't want eager loading of the related objects. Could this be the reason for the error? All help is eagerly anticipated.
public ICollection<InvestmentClubMember> ClubMembers;
should be
public virtual ICollection<InvestmentClubMember> ClubMembers { get; set; }
...or better yet,
public virtual ICollection<InvestmentClubMember> ClubMembers { get; protected set; }
It needs to be virtual in order for the dynamic proxy subclass to be able to populate the navigation property. They will not eager load automatically just because the property is virtual.
The .Include extension method is what does the eager loading.
ClubMembers is declared as a field, but EntityFramework requires it to be a property. Declare it as following:
public ICollection<InvestmentClubMember> ClubMembers { get; set; };