First of all, I’m new to the EF-code first and .NET in general.
Im working on a mobile web app thats being built with MVC4, EF, JQuery, AutoMapper & other technologies and libraries.
This might be confusing, but I will do my best to explain it right.
I have the following pocos:
public class Test
{
[Key]
public int TestId { get; set; }
.
.
Other properties
.
.
public virtual ICollection<Question> Questions { get; set; }
public virtual ICollection<UserStatus> UserStatuses { get; set; }
}
public class UserStatus
{
[Key]
public int UserStatusId { get; set; }
public int TestId { get; set; }
public string Customer { get; set; }
.
.
Other properties
.
.
}
public class Question
{
[Key]
public int QuestionId { get; set; }
public int TestId { get; set; }
.
.
Other properties
.
.
}
and in my context class i have:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<CmeContext>(null);
modelBuilder.Entity<Test>()
.HasKey(a => new { a.TestId })
.HasMany(s => s.Questions);
modelBuilder.Entity<Test>()
.HasKey(a => new { a.TestId })
.HasMany(s => s.UserStatuses);
}
The above Test object has a one-to-many relationship to Question and UserStatus objects through TestId. Each Test has it’s own set of questions which are 4 questions per test, and 20 userStatuses 5 per question).
As the name implies the UserStatus table has user statuses; it let me know which question(s) from what test was answered by a user.
The code in the controller:
var filtered = (from test in _ctxCmeContext.Test.Include("UserStatus").Include("Question")
where test.Program == "SomeProgram" && test.IssueDate.Value.Year == year && test.IssueDate.Value.Month == monthNumber
orderby test.IssueDate descending
select new { test,
Questions = test.Questions,
UserStatuses = test.UserStatuses.Where(x => x.Customer == currentUserId) });
As you see I have an anonymous class so I can get the UserStatuses collection filtered by currentUserId to get the statuses for the current user only. Everything works fine at this point.
Here’s what I need to do:
Each question needs to know its own status, so it’s a one-to-one relationship between the Question and UserStatus table
In my context class I added the following:
modelBuilder.Entity<Question>()
.HasRequired(x => x.UStatus)
.WithOptional();
and in the Question Object I had:
public virtual UserStatus UStatus { get; set; }
and I also modified my linq statement as follows:
var filtered = (from test in _ctxCmeContext.Test.Include("UserStatus").Include("Question").Include("UStatus")
where test.Program == "SomeProgram" && test.IssueDate.Value.Year == year && test.IssueDate.Value.Month == monthNumber
orderby test.IssueDate descending
select new { test,
QuestionStatus = test.Questions.Select(u=>u.UStatus),
Questions = test.Questions,
UserStatuses = test.UserStatuses.Where(x => x.Customer == currentUserId) });
The result:
the UStatus property had data for each question but it wasn’t for the current user nor for the right test; it seemed to me that it just grabbed the first record it ecountered that had the same QuestionId from the Question table. No good.
so I changed the relationship to one-to-many:
In my context class I replaced:
modelBuilder.Entity<Question>()
.HasRequired(x => x.UStatus)
.WithOptional();
with:
modelBuilder.Entity<Question>()
.HasKey(a => new { a.QuestionId })
.HasMany(s => s.UStatus);
changed the UStatus property in the Question Object to:
public virtual ICollection<UserStatus> UStatus { get; set; }
and removed the following from the linq statement
QuestionStatus = test.Questions.Select(u=>u.UStatus),
This time I was able to get some correct data but only for the first 4 questions, and the rest were null
I don’t know what to do anymore. Help me please.
In the Question object I created a navigation property back to the Test object, and from there I was able to know the status of each question because the UserStatus is a child collection in the Test object.