0

While using LinQ, retrieving data from foreign key table data are available. But when I try to 'Add' into my ViewModel this warnings shows. Warningsare difference from each other. such as,

Cannot implicitly convert type 'System.Collection.Generic.IEnumerable<string>' to 'string'

and

Cannot implicitly convert type 'System.Collection.Generic.IEnumerable<System.Collection.Generic.IEnumerable.IEnumerable<string>' to 'string'.

I tried casting to ToString() but it was worthless, no errors shows but data was replaced with system messages. I also tried to LinQ Join in students but I was unable to show Skills Comma Separated that way.

Here is my code:

         public ActionResult GetStudentsInfo ()
        {
            var students = (from stud in db.Students
                            group stud by stud.StudentId into sg

                            select new
                            {
                                studentName=sg.Select(s=>s.StudentName).FirstOrDefault(),
                                coutryName=sg.Select(c=>c.Country.CountryName),
                                cityName=sg.Select(ct=>ct.Country.Cities.Select(x=>x.CityName)),
                                skillName=sg.Select(sk=>sk.StudentSkills.Select(s=>s.Skill.SkillName)),
                                resumeName=sg.Select(r=>r.Resumes.Select(m=>m.ResumeName)),
                                dob=sg.Select(d=>d.DateOfBirth)

                            }).ToList();

            List<StudentListVM> studentLists=new List<StudentListVM>();

            foreach (var item in students)
            {
                studentLists.Add(new StudentListVM
                {
                    studentName = item.studentName,
                    country = item.coutryName, //warnings here
                    city = item.cityName, //warnings here
                    skills = string.Join(",", item.skillName),
                    resume = item.resumeName, //warnings here
                    dateOfBirth = item.dob //warnings here
                });
            }
            return View(studentLists);

        }

          ```

StudentListVM class



 public class StudentListVM
    {
        public string studentName { get; set; }
        public string country { get; set; }
        public string city { get; set; }
        public string skills { get; set; }
        public string resume { get; set; }
        public DateTime dateOfBirth { get; set; }
    }

    ```

I tried this before


 var students = (from stud in db.Students
                            join con in db.Countries on stud.CountryId equals con.CountryId
                            join ct in db.Cities on stud.CityId equals ct.CityId
                            join rsm in db.Resumes on stud.ResumeID equals rsm.ResumeId
                            join stsk in db.StudentSkills on stud.StudentId equals stsk.StudentId
                            //group stud by stud.StudentId into sg

                            select new StudentListVM()
                            {

                                studentName = stud.StudentName,
                                countries = con.CountryName,
                                cities = ct.CityName,
                                skills=stsk.Skill.SkillName,
                                resumes = rsm.ResumeName,
                                dateOfBirth = stud.DateOfBirth,



                            }).ToList();
        ```


StudentSkill class:

     public partial class StudentSkill
{
    public int StudentSkillsId { get; set; }
    public int StudentId { get; set; }
    public int SkillId { get; set; }

    public virtual Student Student { get; set; }
    public virtual Skill Skill { get; set; }
}

    ```

This returns All fine except The Skills in a comma separated list. All I need to show my multiple skills that are checked multiply and added to the database in a separated table name StudentSkills. Is there any good solution to do it?

SagarFi
  • 17
  • 1
  • 8
  • 1
    which line of code is throwing the error – Baahubali Mar 06 '20 at 02:09
  • @Baahubali Ok, i am specifying it in my code – SagarFi Mar 06 '20 at 02:14
  • @Bahubali, In the foreach statement, not errors actually, red warnings – SagarFi Mar 06 '20 at 02:16
  • Does this answer your question? [Linq Query : Cannot convert type IEnumerable to string changing .ToString() to (string)](https://stackoverflow.com/questions/16512316/linq-query-cannot-convert-type-ienumerablestring-to-string-changing-tostrin) – devNull Mar 06 '20 at 02:53

3 Answers3

0

You are trying to assign a group of strings, specifically the various IEnumerable<string> collections, into a single string due to your Select() calls.

For example, this line is clearly selecting more than one resume name.

resumeName=sg.Select(r=>r.Resumes.Select(m=>m.ResumeName))

If you don't care and expect them to be all the same value you could just grab the first one:

resume = item.resumeName.FirstOrDefault()

Or flatten the collection some other way.

That said, there's something off with the design when you grab a collection and try to assign it to a single item.

Zer0
  • 7,191
  • 1
  • 20
  • 34
  • No, I want the dynamic way, like skills, resumes also can be multiple. Actually I can do them separately in different ways but I can't do it in a single code. It will be better if there is any finest way to do this. – SagarFi Mar 06 '20 at 02:33
0

The problem you have is not in your code. The problem is how you think you are solving it. Think it right, the solution will be right. @Zer0 already mentioned that but you probably need more explanation. I will try to explain with some assumption that you might be wanting to do --

1: If Student can have multiple country, city, skill and resumes, then the StudentVM class you have is most certainly wrong. By definition it only supports one city, country, skill, etc. Modify it to support multiples -

public class StudentListVM
{
    public string studentName { get; set; }
    public List<string> countries { get; set; }
    public List<string> cities { get; set; }
    public string skills { get; set; }
    public List<string> resume { get; set; }
    //does not make sense to have a list, a person has only one DOB
    public DateTime dateOfBirth { get; set; }
}

then the code you have will work -

public ActionResult GetStudentsInfo ()
    {
        var students = (from stud in db.Students
                        group stud by stud.StudentId into sg

                        select new
                        {
                            studentName=sg.Select(s=>s.StudentName).FirstOrDefault(),
                            coutryName=sg.Select(c=>c.Country.CountryName),
                            cityName=sg.Select(ct=>ct.Country.Cities.Select(x=>x.CityName)),
                            skillName=sg.Select(sk=>sk.StudentSkills.Select(s=>s.Skill.SkillName)),
                            resumeName=sg.Select(r=>r.Resumes.Select(m=>m.ResumeName)),
                            dob=sg.Select(d=>d.DateOfBirth).FirstOrDefault()

                        }).ToList();

        List<StudentListVM> studentLists=new List<StudentListVM>();

        foreach (var item in students)
        {
            studentLists.Add(new StudentListVM
            {
                studentName = item.studentName,
                countries = item.coutryName.ToList(), //should work, as these are lists
                cities = item.cityName.ToList(), //should work, as these are lists
                skills = string.Join(",", item.skillName),
                resume = item.resumeName.ToList(), //should work, as these are lists
                dateOfBirth = item.dob //does not make sense to have a list, a person has only one DOB
            });
        }
        return View(studentLists);
}

2: Once the class is okay, you could shorten the code. You don't need a second block to create a typed list, you can do it directly -

public ActionResult GetStudentsInfo ()
    {
        var students = (from stud in db.Students
                        group stud by stud.StudentId into sg

                        select new StudentListVM
                        {
                            studentName=sg.Select(s=>s.StudentName).FirstOrDefault(),
                            countries=sg.Select(c=>c.Country.CountryName).ToList(),
                            cities=sg.SelectMany(ct=>ct.Country.Cities.Select(x=>x.CityName)).ToList(),
                            skills=string.Join(",", sg.Select(sk=>sk.StudentSkills.Select(s=>s.Skill.SkillName))),
                            resume=sg.SelectMany(r=>r.Resumes.Select(m=>m.ResumeName)).ToList(),
                            //does not make sense to have a list, a person has only one DOB
                            dob=sg.Select(d=>d.DateOfBirth).FirstOrDefault()

                        }).ToList();
   return View(students);
}

3: If the above does not make sense, then the idea is not right. Think of what you are trying to achieve and update the question. May be then people will be able to help.

You have said -

Actually I can do them separately in different ways but I can't do it in a single code

So what are those ways? Mentioning them will probably give an idea of what you are trying to achieve. The details on the question is not enough to give you solution. It does not say what you are trying to do.

brainless coder
  • 6,310
  • 1
  • 20
  • 36
  • I want a list that have all the columns above, I can do it by LINQ Join and it works, the only problem in the skill column that doesn't work in that way and cannot being added by a separate code that I know, which is Grouping them and Add by a foreach statement. So I am trying my own in a unknown way. I will try in your way and let you know after that. – SagarFi Mar 06 '20 at 03:43
  • Sorry! cities and resumes are still getting the same warnings from your solution. Whats the solution then? – SagarFi Mar 06 '20 at 04:05
  • Probably because this is a double select `sg.Select(ct=>ct.Country.Cities.Select(x=>x.CityName))`. try `SelectMany` I have updated the answer. This is will flatten the list and I recommend reading about it first - https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.selectmany?view=netframework-4.8 – brainless coder Mar 08 '20 at 22:54
  • BTW, I was not giving a solution, the whole structure needs fix. So, I would recommend re think your strategy and re implement it. – brainless coder Mar 08 '20 at 22:58
0

Try to change this line:

skills = string.Join(",", item.skillName),

With this:

skills = string.Join(",", item.skillName.ToArray()),
svladimirrc
  • 216
  • 1
  • 6