how to reach a class's property in LINQ - c#

I am trying to find unread messages count with linq. I am counting if message's lastmodified date greater than user's LastViewedOn date. My ConversationMembers class has LastViewedOn property. But i couldn't find a way to reach users's LastViewedOn property..
.Count(x => x.ConversationMembers
.Where(y => y.MembershipId.Value == membershipId)
.Any(y => y.LastViewedOn == null)
||
x.ConversationMessages.OrderByDescending(message => message.LastModifiedOn)
.Any(z => z.LastModifiedOn > x.ConversationMembers
.Where(y => y.MembershipId.Value == membershipId)
.Select()
.LastViewedOn.Value
)); //here i m trying to reach LastViewedOn value but it not work
Please can you help me about how can i reach that value?
Here my ConversationMember class
public class ConversationMember
{
public Guid Id { get; set; }
public Guid ConversationId { get; set; }
public virtual Conversation Conversation { get; set; }
public Guid? MembershipId { get; set; }
public DateTime? LastViewedOn { get; set; }
}
here ConversationMessage class
public class ConversationMessage
{
public Guid Id { get; set; }
[Required]
public string Text { get; set; }
public Guid ConversationId { get; set; }
public virtual Conversation Conversation { get; set; }
public Guid? MembershipId { get; set; }
[Required]
[Column(TypeName = "datetime2")]
public DateTime LastModifiedOn { get; set; }
}
And here conversation class
public class Conversation
{
public Guid Id { get; set; }
public virtual ICollection<ConversationMember> ConversationMembers { get; set; }
public virtual ICollection<ConversationMessage> ConversationMessages { get; set; }
[Required]
public DateTime LastModifiedOn { get; set; }
}

Try changing your LINQ to this:
.Count(x => x.ConversationMembers.Where(y => y.MembershipId.Value == membershipId)
.Any(y => y.LastViewedOn == null) || x.ConversationMessages.OrderByDescending(message => message.LastModifiedOn)
.Any(z => z.LastModifiedOn > x.ConversationMembers.FirstOrDefault(y => y.MembershipId.Value == membershipId).LastViewedOn.Value));

Related

How to construct a specific linq query?

I have three tables, doctor, office and appointment. Office table has DoctorId as a foreign key, and Apponitment has a foreign key OfficeId. I want to fetch all the appointments that have OfficeId equal to Ids in the list of offices that have the same doctorId. Specifically, I don't know how to extract ids from the list of offices. Here is my code, I skipped some parts for brevity:
public class Appointment1 : BaseEntity
{
public int? Patient1Id { get; set; }
[ForeignKey("Patient1Id")]
public Patient1 Patient { get; set; }
public int Office1Id { get; set; }
[ForeignKey("Office1Id")]
public Office1 Office { get; set; }
[DataType(DataType.Date)]
public DateTime StartDateAndTimeOfAppointment { get; set; }
[DataType(DataType.Date)]
public DateTime EndDateAndTimeOfAppointment { get; set; }
public bool? Status { get; set; }
public string Remarks { get; set;}
}
public class Doctor1 : BaseEntity
{
public int ApplicationUserId { get; set; }
[ForeignKey("ApplicationUserId")]
public ApplicationUser ApplicationUser { get; set; }
public string Name { get; set; }
public string Resume { get; set; }
}
public class Office1 : BaseEntity
{
public int Doctor1Id { get; set; }
[ForeignKey("Doctor1Id")]
public Doctor1 Doctor { get; set; }
public decimal InitialExaminationFee { get; set; }
public decimal FollowUpExaminationFee { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
public async Task<List<Appointment1>> GetAppointmentsWithSearchingAndPaging(QueryParameters queryParameters,
int userId)
{
var doctor = await _context.Doctors1.Where(x => x.ApplicationUserId == userId)
.FirstOrDefaultAsync();
var office = await _context.Offices.Where(x => x.Doctor1Id == doctor.Id)
.FirstOrDefaultAsync();
IQueryable<Appointment1> appointment = _context.Appointments1.Include(x => x.Patient)
.Where(x => x.Office1Id == office.Id)
.AsQueryable().OrderBy(x => x.Id);
if (queryParameters.HasQuery())
{
appointment = appointment
.Where(x => x.Office.Street.Contains(queryParameters.Query));
}
appointment = appointment.Skip(queryParameters.PageCount * (queryParameters.Page - 1))
.Take(queryParameters.PageCount);
return await appointment.ToListAsync();
}
The problem is with office which gives firstordefaultasync, and should give list, because I want all the ids, but in the end I get only appointments that have one identical officeid as a foreign key...thanks in advance!
Here is the answer, I needed this part of code, my question was not precise so I appologize:
var offices = await _context.Offices.Where(x => x.Doctor1Id == doctor.Id)
.ToListAsync();
IEnumerable<int> ids = offices.Select(x => x.Id);
IQueryable<Appointment1> appointment = _context.Appointments1.Include(x => x.Patient)
.Where(x => ids.Contains(office.Id))
.AsQueryable().OrderBy(x => x.Id);

EF Core Add() only adds the last element to an ICollection

I'm trying to add an element to an ICollection object in EF Core 5. But only the last element remains on the list.
As an example, When a student submits an answer, I want to add him to the Participants of the exam(A). It works as it should. But when the same person submits another exam(B). His records are lost from the previous exam(A).
Here is my code.
SubmitExam Method in ExamController.cs
[HttpPost("submit")]
public async Task<ActionResult<GetExamDTO>> SubmitExam(GetExamDTO getExamDTO)
{
var username = User.FindFirst(ClaimTypes.Name).Value;
var user = await _userManager.Users
.Where(u => u.UserName == username)
.Include(u => u.ParticipatedExams)
.ThenInclude(er => er.Exam)
.FirstOrDefaultAsync();
if (user == null)
return Unauthorized("Invalid User");
var exam = await _dbContext.Exams
.Where(e => e.Id == getExamDTO.Id)
.Include(e => e.Creator)
.Include(e => e.Participants)
.Include(exam => exam.Questions)
.ThenInclude(question => question.Options)
.AsSplitQuery()
.SingleOrDefaultAsync();
if (exam == null)
return BadRequest("Invalid Exam Id");
if (!exam.SubmissionEnabled)
return BadRequest("Exam is over. You are too late.");
double marksObtained = 0;
double negativeMarksObtained = 0;
for (int i = 0; i != getExamDTO.Questions.Count(); ++i)
{
var question = exam.Questions.ElementAt(i);
if (question.CorrectAnswerText == getExamDTO.Questions[i].ProvidedAnswer.Text)
{
marksObtained += question.Marks;
}
else
{
marksObtained -= exam.NegativeMarks;
negativeMarksObtained -= exam.NegativeMarks;
}
}
var participatedFromExam = exam.Participants.Where(u => u.Id == user.Id)
.SingleOrDefault();
var participatedFromUser = user.ParticipatedExams
.Where(er => er.ExamId == exam.Id)
.SingleOrDefault();
System.Console.WriteLine("Submit" + participatedFromExam);
if (participatedFromExam == null && participatedFromUser == null) // If user sits for the first time, count him as new.
{
exam.Participants.Add(user); // Participants gets empty for every exam except the last submitted one. It fried my brain.
++exam.Attendees;
if (await _dbContext.SaveChangesAsync() > 0)
System.Console.WriteLine("Added submission");
var result = new ExamResult
{
Exam = exam,
Score = marksObtained
};
user.ParticipatedExams.Add(result);
await _userManager.UpdateAsync(user);
}
var examDto = examToDto(exam);
examDto.Participated = true;
examDto.MarksObtained = marksObtained;
examDto.Questions = getExamDTO.Questions;
examDto.NewSubmission = true;
examDto.NegativeMarks = negativeMarksObtained;
return Ok(examDto);
}
EntityUser.cs
public class EntityUser : IdentityUser
{
public ICollection<ExamResult> ParticipatedExams { get; set; }
public DateTime? LastActive { get; set; } = DateTime.UtcNow;
}
Exam.cs
public class Exam
{
public string Title { get; set; }
public Guid Id { get; set; }
public int Attendees { get; set; } = 0;
public string CreatorId { get; set; }
public EntityUser Creator { get; set; }
public DateTime CreatedAt { get; set; }
public int Duration { get; set; }
public double TotalMarks { get; set; }
public double NegativeMarks { get; set; }
public bool SubmissionEnabled { get; set; }
public ICollection<Question> Questions { get; set; }
public ICollection<EntityUser> Participants { get; set; }
}
ExamResult.cs
public class ExamResult
{
public Guid Id { get; set; }
public Exam Exam { get; set; }
public Guid ExamId { get; set; }
public double Score { get; set; }
}
GetExamDTO.cs
public class GetExamDTO
{
public string Title { get; set; }
public Guid Id { get; set; }
public int Attendees { get; set; } = 0;
public string Subject { get; set; }
public string CreatorId { get; set; }
public string Creator { get; set; }
public DateTime CreatedAt { get; set; }
public int Duration { get; set; }
public double TotalMarks { get; set; }
public double MarksObtained { get; set; }
public double NegativeMarks { get; set; }
public bool SubmissionEnabled { get; set; }
public bool Participated { get; set; }
public bool NewSubmission { get; set; }
public List<QuestionDTO> Questions { get; set; }
public List<ParticipantDTO> Participants { get; set; }
}
I will appreciate any help. Thanks in Advance.
fix the Examresult class by adding UserId
public partial class ExamResult
{
public Guid Id { get; set; }
public int? UserId { get; set; }
public virtual EntityUser User { get; set; }
public Guid ExamId { get; set; }
public virtual Exam Exam { get; set; }
public double Score { get; set; }
}
public partial class EntityUser : IdentityUser
{
public virtual ICollection<ExamResult> ParticipatedExams { get; set; }
public DateTime? LastActive { get; set; } = DateTime.UtcNow;
}
you can try to add fluent api to your db context
public virtual DbSet<ExamResult> ExamResults { get; set; }
.....
modelBuilder.Entity<ExamResult>(entity =>
{
entity.HasOne(d => d.User)
.WithMany(p => p.ParticipatedExams)
.HasForeignKey(d => d.UserId);
});
and code
var result = new ExamResult
{
UserId=user.Id,
ExamId = exam.Id,
Score = marksObtained
};
_dbContext.ExamResults.Add(result)
await _dbContext.SaveChangesAsync();

Filter a list Using Linq C#

public class Orgs
{
public int Id { get; set; }
public DateTime OrgCreationTime { get; set; }
public string AppUserId { get; set; }
public virtual ICollection<OrgPersonRelationshipDomain> ManyOrgPersonRelationship { get; set; }
}
public class OrgPersonRelationshipDomain
{
//public int ID { get; set; }
public int OrgId { get; set; }
public virtual OrgDomain Org { get; set; }
public bool IsDeleted { get; set; }
}
var orgs = await _context.Org.Where(x => x.Id == request.Id).ToListAsync();
How to filter list where "orgs" should give result with IsDeleted!= true?
Result I am getting is only ManyOrgPersonRelationship item but I want Orgs properties included in it.
`
Try this :
var orgs = _context.Org.Where(x => x.AppUserId == userId && x.ManyOrgPersonRelationship.Any(x => x.IsDeleted != false)).ToList();

One to Many relationship always bring me empty

I try to use Entity Framework with code first and fluent api to implement a one to many relationship
I have two classes
namespace Mantenimiento.Business.Entities
{
public class Personal : Entity
{
[Key]
public int Id { get; set; }
public int? Dni { get; set; }
public string Nombre { get; set; }
public string Apellido { get; set; }
public string Cuil { get; set; }
public string Legajo { get; set; }
[ForeignKey("Dni")]
public ICollection<ContactoEmergencia> Contacto { get; set; }
}
namespace Mantenimiento.Business.Entities
{
public class ContactoEmergencia : Entity
{
[Key]
public int Id { get; set; }
public int? Dni { get; set; }
public string ApellidoNombre { get; set; }
public string Vinculo { get; set; }
public string Domicilio { get; set; }
public string telefono { get; set; }
public string Comentario { get; set; }
public int CreateUserId { get; set; }
[ForeignKey("Dni")]
public virtual Personal Personal { get; set; }
}
}
This is my dbContext
#region personals
modelBuilder.Entity<Personal>().ToTable("InfoPersonal").HasKey(t => t.Id);
modelBuilder.Entity<Personal>().Property(c => c.Id).UseSqlServerIdentityColumn().IsRequired();
modelBuilder.Entity<Personal>().Property(c => c.CreatedDate).HasDefaultValue(DateTime.Now);
modelBuilder.Entity<Personal>().Property(c => c.LastModifiedDate).HasDefaultValue(DateTime.Now);
modelBuilder.Entity<Personal>().Property(c => c.Deleted).HasDefaultValue(false);
modelBuilder.Entity<Personal>().HasMany<ContactoEmergencia>(c => c.Contacto).WithOne(p => p.Personal).HasForeignKey(s => s.Dni);
#endregion
#region contactoEmergencias
modelBuilder.Entity<ContactoEmergencia>().ToTable("InfoEmergencia").HasKey(d => d.Dni);
modelBuilder.Entity<ContactoEmergencia>().Property(c => c.CreatedDate).HasDefaultValue(DateTime.Now);
modelBuilder.Entity<ContactoEmergencia>().Property(c => c.LastModifiedDate).HasDefaultValue(DateTime.Now);
modelBuilder.Entity<ContactoEmergencia>().Property(c => c.Deleted).HasDefaultValue(false);
#endregion
And my query is
return await _context.personals
.Include(c => c.Contacto)
.Where(p => p.Deleted == false)
.OrderBy(s => s.Apellido)
.ToListAsync(
);
But the properties is always empty.
i need to relate Personal.Di with Contacto.Dni, i had to change the key?
You should remove ForeignKey attribute from Personal entity. In one to many relationship only child entity could accept ForeignKey.

How do I make this Linq to SQL query with lambdas and includes faster?

I have this piece of code which performs quite poorly, and delays loading of web pages as a result. The objects underlying the query are not overly complicated and I only have around 6,000 rows in the time entry table, and a small number of rows in the included tables.
How can I re-write it to be more efficient? Why is it so slow? Is it the multiple includes, the lambdas, or the ToList()? When I remove the ToList() it is quite fast, but the code following this query expects a list of time entries, so I would like to find a faster alternative that still returns a list.
var timeEntries = db.TimeEntries
.Include(t => t.Assignment)
.Include(t => t.TimeStatus)
.Include(t => t.User)
.Where(t => t.UserID == strCurrentUserId)
.Where(t => t.TimeDate >= wcDate && t.TimeDate <= sundayDate)
.OrderBy(t => t.TimeDate)
.ToList();
A few of the classes are below (but, I'm not exposing my user class):
public class TimeEntry
{
[Key]
public int ID { get; set; }
public int AssignmentID { get; set; }
public virtual Assignment Assignment { get; set; }
public DateTime TimeDate { get; set; }
public decimal TimeUsed { get; set; }
public int TimeStatusID { get; set; }
public TimeStatus TimeStatus { get; set; }
public string UserID { get; set; }
public virtual User User { get; set; }
[DataType(DataType.MultilineText)]
public string Comment { get; set; }
}
public class TimeStatus
{
[Key]
public int ID { get; set; }
public string Status { get; set; }
}
public class Assignment
{
[Key]
public int ID { get; set; }
public int ProjectID { get; set; }
public virtual Project Project { get; set; }
public string UserID { get; set; }
public virtual User User { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int AssignmentStatusID { get; set; }
public AssignmentStatus AssignmentStatus { get; set; }
public decimal ChargeRate { get; set; }
public int MaxDays { get; set; }
public bool Billable { get; set; }
public bool BillableInternal { get; set; }
[Display(Name = "Assignment No.")]
public string AssignmentNumber
{
get
{
return "A" + ID.ToString("D5");
}
set { }
}
}

Categories