Get property from Icollection (ASP.NET MVC) - c#

I have back-end where I need to get FIO from table
I try to write code and here is what I have
public ActionResult Profile_Data_Questions()
{
var dataforprofile = TempData["FIO"];
var profiledata = db.QuestionBlocks
.Where(x => x.Interview.Interwiers == dataforprofile)
}
But Interwiers is IColection
Here is Model for Interwiers
[Key]
public int Interwier_id { get; set; }
[Display(Name = "ФИО")]
public string FIO { get; set; }
public string Email { get; set; }
[Display(Name = "Телефон")]
public string Telephone { get; set; }
[Display(Name = "День рождения")]
[DataType(DataType.Date)]
public string Birthday { get; set; }
[Display(Name = "Город")]
public string City { get; set; }
[Display(Name = "Зарплата")]
public string Salary { get; set; }
[Display(Name = "Английский")]
public string English { get; set; }
public Nullable<int> Interview_Id { get; set; }
[Display(Name = "Статус")]
public string Status { get; set; }
public virtual Interview Interview { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Link> Links { get; set; }
How I can get FIO property?

i assume the dataforprofile is a string or an int / enum, ... you can search the items that have the prop set to dataforprofile.
var profiledata = db.QuestionBlocks
.Where(x => x.Interview.Interwiers.Any(y=> y.prop == dataforprofile))
the code above will give you all questionblocks where there is an interview containing one or more interviewers with the prop set to the dataforprofile var.

Heck I am not sure what your problem is, and I can't ask for clarification yet, due to not having accumulated enough rep. So here goes:
Either your collection does not contain interviewer objects, and you need to convert your request into the object type like so:
var targetList = origList
.Select(x => new TargetType() { SomeValue = x.SomeValue })
.ToList();
Or, if the question is even simpler I will link to another question that answers my other interpretation of your question:
How to expose a collection property?

Related

Get a specific info from an other table with Linq

My database is created using code first. Here is the model for my client.
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Display(Name = "Phone number")]
public int PhoneNumber { get; set; }
[Display(Name = "Email adress")]
[EmailAddress]
public string EmailAdress { get; set; }
[Display(Name = "Date of the wedding")]
public DateTime DateOfTheWedding { get; set; }
[Display(Name = "Type of client")]
public TypeOfClient TypeOfClient { get; set; }
[NotMapped]
public int DaySinceLastVisit { get; set; }
I also have a model Visit :
public int Id { get; set; }
public Client Client { get; set; }
[Required]
[ForeignKey("Client")]
public int ClientId { get; set; }
[Display(Name = "Date of the visit")]
public DateTime DateOfTheVisit { get; set; }
public String Comment { get; set; }
Each client have a multiple visit.
How can I get the last visit and add it to my model ?
Here is my resquest linq that I want to improve.
var clientsQueryable = _context.Clients
.Include(c => c.TypeOfClient);
if (!String.IsNullOrWhiteSpace(query))
clientsQueryable.Where(client => client.FirstName.Contains(query));
var listClients = clientsQueryable
.ToList()
.Select(Mapper.Map<Client, ClientDto>);
return Ok(listClients);
I want to have in Client the info DaySinceLastVisit.
I presume that we need to get the last visit and make a calculation to get the days that have passed since this visit ?
First of all:
If a Client has multiple Visits, it would be good to add a
public virtual ICollection<Visit> Visits { get; set; }
To your Client entity, so you can easily access all the Visits linked to a Client.
Then it's easy to calculate the "DaySinceLastVisit" using similar code like this:
public int DaySinceLastVisit => (DateTime.Now - Visits.OrderByDescending(v => v.DateOfTheVisit).FirstOrDefault().DateOfTheVisit).Days;

ASP.NET MVC multiple models in one view

I have the following models
Patient Class:
public class Patient
{
public int PatientID { get; set; }
public virtual Salutation salutation { get; set; }
public int SalutationID { get; set; }
public string Surname { get; set; }
public string Firstname { get; set; }
[Display(Name = "Date of Birth")]
[DisplayFormat(DataFormatString="{0:d}", ApplyFormatInEditMode=true)]
public DateTime DOB { get; set; }
public string RegNo { get; set; }
public DateTime RegDate { get; set; }
public string Occupation { get; set; }
}
VatalSigns Class
public class VitalSign
{
public int VitalSignID { get; set; }
public string Sign { get; set; }
[Display(Name = "Lower Limit")]
public int? LowerHold { get; set; }
[Display(Name = "Upper Limit")]
public int? UpperHold { get; set; }
[Display(Name = "Unit Of Measurment")]
public string Units { get; set; }
}
PV class that stores VitalSigns for each patient
public class PVSign
{
public long PVSignId { get; set; }
[Display(Name = "Patient")]
public int PatientID { get; set; }
public VitalSign VitalSigns { get; set; }
//public IList<VitalSign> VitalSigns { get; set; }
public Patient patient { get; set; }
}
Now the problem I have is that I have not been able to get display on one from to enter the details. I want to select the Patient and the different Vitals signs will appear and I will save the ones I need to the PVSign table.
I have tired all sorts of samples from the web. You can see from the code below, this is the index stub:
public ActionResult Index()
{
var pVSigns = db.PVSigns.Include(p => p.patient).Include(p => p.PVSignId).Include(p => p.VitalSigns);
//var pVSigns = from o in db.Patients join o2 in db.PVSigns
//List<object> myModel = new List<object>();
//myModel.Add(db.Patients.ToList());
//myModel.Add(db.VitalSigns.ToList());
//return View(myModel);
return View(pVSigns.ToList());
}
How to I solve this issue. I am new to MVC, if it was Webforms, I would have been through with this project.
Thank you.
There is no single answer(solution) to this(your) problem. It depends on how you want to design/build/achieve your solution.
The simple, brute solution : Just have a view model as a wraper that has as his properties the classes(models) you made and work around that,
public class FullPatientDetailsViewModel
{
public Patient { get; set;}
public List<PVSign> PatientPvSigns { get; set;} // Patien PV Signs
}
Or use just a PatientViewModel and load his PVSigns async with Ajax.
There is no simple best solution, it all depends about what do you want to achieve as a bigger picture.
I've answered a similar question here. As Alexandru mentioned, the easiest and most straightforward way would be to wrap your models inside a ViewModel. You can read about other ways to implement this here.

How to seed the database with a many-to-many relationship in Entity Code First

I have a many-to-many relationship in my code and I am trying to seed the database. Here is my seed method:
var loc = new List<Location> {
new Location { LocationName = "Paradise Lane" },
new Location { LocationName = "81st Street" }
};
loc.ForEach(l => context.Locations.Add(l));
var soft = new List<Software> {
new Software { Title = "Adobe Creative Suite", ... Locations = loc.Single(s => s.LocationName = "Paradise Lane")}
};
soft.ForEach(s => context.Software.Add(s));
Here is my locations class:
public class Location
{
public int Id { get; set; }
[Required]
[StringLength(20)]
public string LocationName { get; set; }
public virtual ICollection<Software> Software { get; set; }
}
Here is my software class:
public class Software
{
public int Id { get; set; }
[Required]
[StringLength(128)]
public string Title { get; set; }
[Required]
[StringLength(10)]
public string Version { get; set; }
[Required]
[StringLength(128)]
public string SerialNumber { get; set; }
[Required]
[StringLength(3)]
public string Platform { get; set; }
[StringLength(1000)]
public string Notes { get; set; }
[Required]
[StringLength(15)]
public string PurchaseDate { get; set; }
public bool Suite { get; set; }
public string SubscriptionEndDate { get; set; }
//[Required]
//[StringLength(3)]
public int SeatCount { get; set; }
public virtual ICollection<Location> Locations { get; set; }
public virtual ICollection<SoftwarePublisher> Publishers { get; set; }
public virtual ICollection<SoftwareType> Types { get; set; }
}
I am getting two errors. One, it tells me I cannot implicitly convert string to bool. I didn't even know I was trying to do t hat. And two, cannot convert lambda express to delegate because soem fo the return types in the block are not implicitly convertable to the delegate return type. Is that a reference to the iCollection?
You missed an equals sign. Double equals for comparing.
loc.Single(s => s.LocationName = "Paradise Lane")
vs
loc.Single(s => s.LocationName == "Paradise Lane")
Also, you can't do a .Single() into Locations because it is an ICollection. Single returns 1 object, not a collection. You should use .Where instead. Or you can implicitly declare an array in there and use your .Single() code inside it.
Edit: Also apparently .Where() doesn't cast nicely to ICollection. Add a ToArray and you'll get an array which is acceptable.

Convert xml to CLR type using Linq

I have following xml structure
<quiz xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="quiz.xsd">
<mchoice>
<question>What is the capital city of Australia?</question>
<answer>Sydney</answer>
<answer correct="yes">Canberra</answer>
<answer>Melbourne</answer>
<answer>Gold Coast</answer>
</mchoice>
</quiz>
and I want to convert it into CLR type using following code
public class Question
{
public int ID { get; set; }
public string QuestionText { get; set; }
public List<Answer> Answers { get; set; }
}
public class Answer
{
public string Answer1 { get; set; }
public string Answer2 { get; set; }
public string Answer3 { get; set; }
public string Answer4 { get; set; }
}
public List<Question> GetAll()
{
var doc = XDocument.Load(Filepath);
var results = (from x in doc.Descendants("mchoice")
select new Question()
{
ID = Convert.ToInt16(x.Element("ID")),
QuestionText = x.Element("question").Value.ToString(),
Answers = new List<Answer>()
{
//How I would fill Answer collection
}
}).ToList();
return results;
}
Now I have two problem with current design.
How I would fill the Answer collection
How I would handle correct answer attribute in current design.
with first idea
public class Question
{
public int ID { get; set; }
public string QuestionText { get; set; }
public Answer Answer { get; set; }
}
public class Answer
{
public string Answer1 { get; set; }
public string Answer2 { get; set; }
public string Answer3 { get; set; }
public string Answer4 { get; set; }
}
var results = (from x in doc.Descendants("mchoice")
let answers = x.Elements("answer")
select new Question()
{
ID = Convert.ToInt16(x.Element("ID")),
QuestionText = x.Element("question").Value,
Answer = new Answer
{
Answer1 = answers.First().Value,
Answer2 = answers.Skip(1).First().Value,
Answer3 = answers.Skip(2).First().Value,
Answer4 = answers.Last().Value
}
}).ToList();
with an easier Model
public class Question
{
public int ID { get; set; }
public string QuestionText { get; set; }
public List<string> AnswerTextList { get; set; }
}
var results = (from x in doc.Descendants("mchoice")
select new Question()
{
ID = Convert.ToInt16(x.Element("ID")),
QuestionText = x.Element("question").Value,
AnswerTextList = (x.Elements("answer").Select(m => m.Value.ToString()).ToList())
}).ToList();
with a GOOD model
public class Question
{
public int ID { get; set; }
public string QuestionText { get; set; }
public List<Answer> AnswerList { get; set; }
}
public class Answer
{
public string Text { get; set; }
public bool IsCorrect { get; set; }
}
var results = (from x in doc.Descendants("mchoice")
select new Question()
{
ID = Convert.ToInt16(x.Element("ID")),
QuestionText = x.Element("question").Value,
AnswerList = (x.Elements("answer").Select(m => new Answer
{
Text = m.Value,
IsCorrect = m.Attribute("correct") != null && m.Attribute("correct").Value == "yes"
}).ToList())
}).ToList();
It looks like there is a mismatch in your model. You have four separate "Answer" properties in the Answer class. However, your Question class contains a list of Answer objects. And the XML contains four answers corresponding to a single question. It seems like a more accurate model of a question would look something like either:
public class Question
{
public int ID { get; set; }
public string QuestionText { get; set; }
public List<string> Answers { get; set; }
public int CorrectAnswerIndex { get; set; }
}
in which case the Answer class could be ignored entirely,
or, you could keep the Question class as is and change the Answer class to look more like
public class Answer
{
public string AnswerText { get; set; }
public bool IsCorrect { get; set; }
}
If you use either of these approaches, it will be much easier to see how you can do the XML mapping. However, as you have presented the problem, there is no correct answer, because the design is fundamentally flawed.
With the first example, you could do the XML-Object mapping as #L.B. suggests. However, you would need to set the CorrectAnswerIndex property equal to the index of the correct answer string in the list.

Strongly Typed List.GroupBy()

I've been trying to find an answer to this on google and on SO
but everywhere I have found uses anonymously typed result lists
what I am trying to acheive is to take a List<SecondaryStandard>
and create a grouped List of SecondaryStandard
each SecondaryStandard looks like this
public class SecondaryStandard
{
public string Id { get; set; }
public int IdNumeric { get; set; }
public string IdText { get; set; }
public Sample Sample { get; set; }
public string StandardName { get; set; }
public DateTime DateCompleted { get; set; }
public SamplePoint SamplingPoint{ get; set; }
public Instrument Instrument{ get; set; }
public string ContainerId { get; set; }
public double Value { get; set; }
public string ComponentName { get; set; }
public string PointLocation { get; set; }
public string Description { get; set; }
public string Description2 { get; set; }
public string Analysis { get; set; }
public string Units { get; set; }
}
what i want is a List() where the Value Property is an average of results for each ComponentName.
Any ideas on how I could achieve this in a strongly typed way or do I need to suck it up and use anonymous objects to achieve what I'm looking for?
You mean this?
List<SecondaryStandard> list = new List<SecondaryStandard>();
// populate list
List<SecondaryStandard> result = list
.GroupBy(l => l.ComponentName)
.Select(s => new SecondaryStandard() { ComponentName = s.Key, Value = s.Average(x => x.Value) }).ToList();

Categories