-1

I have two database tables that are linked by an attribute in one of the tables. The tables are being separately represented as models in an ASP .NET core MVC app. In a controller action, I have a linq query that performs a join on the two tables and selects a set of columns from the join results. I'm trying to send this result set to a view page so that the data can be displayed in a paginated table, but I'm not sure how exactly this should be done.

In the past, when using ASP .NET MVC (not core), I've been able to execute stored procedures that return result sets in controller actions, iterate through the result sets, build up lists with the data and then store the lists in the viewbag which can be accessed in the view. I've tried to directly store the EntityQueryable object in the viewbag but I got an error and I'm not sure how I would go about iterating through it anyway.

What would be the best way to send the data returned from the linq query to the View page?

Controller Action code:

 var resultsObj = (from rd in _db.ResData
                                  join ra in _db.ResAvailability on rd.RecNo equals ra.RecNoDate
                                  where ra.TotalPrice < Int32.Parse(resDeals.priceHighEnd) && ra.TotalPrice > Int32.Parse(resDeals.priceLowEnd)

                                  select new
                                  {
                                      Name = rd.Name,
                                      ImageUrl = rd.ImageUrl,
                                      ResortDetails = rd.ResortDetails,
                                      CheckIn = ra.CheckIn,
                                      Address = rd.Address,
                                      TotalPrice = ra.TotalPrice
                                  }).Take(10);
                ViewBag.resultSet = resultsObj;

EDIT:

My query is returning data that from multiple tables (since it is a join) so data from the query results has to be extracted and separated into the two different viewmodels which correspond to the tables in the join.

The first viewmodel represents each row of the query results. The second viewmodel is just a list to hold all of the rows that are contained in the query results. I'm trying to understand how to do the data extraction from the query results into the viewmodels as I have explained here.

loremIpsum1771
  • 2,497
  • 5
  • 40
  • 87

1 Answers1

0

I would return a ViewModel instead. Generally you may use it to send the data to/from the View and controller.

I am currently working on a big project, and ViewModels work pretty well for me.

Check this short video:

https://www.youtube.com/watch?v=m086xSAs9gA

UPDATE

I am assuming that your query works properly (I did not read it).

To send your data via a ViewModel to the View.

First create the required ViewModel classes:

public class PageNameViewModel
{
    public string Name { get; set; }
    public IEnumerable<ResortDetailViewModel> ResortDetailViewModels { get; set; }
    ... rest of properties are not shown for clarity ...
}

public class ResortDetailViewModel
{
    public string Detail1 { get; set; }
    public int Detail2 { get; set; }
    ... etc. ...
}

Now use the ViewModels in the controller (or let us say, fill the data in the viewmodel):

var viewModel = (from rd in _db.ResData
                                  join ra in _db.ResAvailability on rd.RecNo equals ra.RecNoDate
                                  where ra.TotalPrice < Int32.Parse(resDeals.priceHighEnd) && ra.TotalPrice > Int32.Parse(resDeals.priceLowEnd)
                                  .Take(10)
                                  select new ClassNameViewModel
                                  {
                                      Name = rd.Name,
                                      ImageUrl = rd.ImageUrl,
                                      ResortDetailViewModels = rd.ResortDetails.Select(o => 
                                                                          new ResortDetailViewModel
                                                                          {
                                                                               Detail1 = o.detail1,
                                                                               Detail2 = o.detail2,
                                                                               ... etc. ...
                                                                          },
                                      CheckIn = ra.CheckIn,
                                      Address = rd.Address,
                                      TotalPrice = ra.TotalPrice
                                  });

return View(viewModel);

Now you can use the ViewModel in the View (I assume you know how, as you watched the view I linked).

Notice that ViewModels should ideally hold primitive data in this case (that will make your life easier if you plan later to serialize the ViewModel and send it to another client).

In the above code, I converted any complex types to primitive types, and that should be on each element (notice I did the same on ResortResults, as I converted them to an array of ViewModel, i.e., array of an objects that only holds primitive data, so no deep hierarchy).

I also moved Take(10) to the upper side of the code, so you do not need to create a ViewModel for each element, and then take only 10! that is just wasting of performance for nothing. By moving it to the upper side, we take the 10 elements before creating the ViewModels, i.e., we create the ViewModels for only the required elements.

I hope that helps. If you need any further help, please please tell me.

Mohammed Noureldin
  • 14,913
  • 17
  • 70
  • 99
  • Thanks for the link, I watched the video. What I'm trying to understand is how exactly the viewmodel should be used in this case. Should it be used to store each row of the query results or the entire set of rows, in which case, the viewmodel would be returned from the controller action and passed to the view. I'm just not sure how to structure the viewmodel so that it exposes the returned data as an iterable object in the view page. A simple code example would help. Thanks – loremIpsum1771 May 06 '18 at 22:10
  • @loremIpsum1771, ok as I said, I solved such problems in the project I am working on a lot of times. Just in short, you want to structure the viewmodel correctly to be able to iterate through some objects in a proper way, is that right? Also please tell which part of of that object is a collection of objects? only ReportDetails? Just give me those infos and I will be happy to rewrite that code for you to be suitable for MVVM pattern. – Mohammed Noureldin May 06 '18 at 23:46
  • Yes, so I'm still new to link and derived my linq query from an example I found. The query takes 10 rows (if I understand correctly) from the result set (`.Take(10)`) so the way I understand it is that `resultsObj` will store that queryable object which contains 10 rows from the database. It seems like you're saying to store `resultsObj` as an attribute of a viewmodel object which would be returned by the action and included in the view page. If that is the case, I'm not sure how I could iterate through the `resultsObj` attribute of the viewmodel to generate the html table I'm trying to make. – loremIpsum1771 May 07 '18 at 03:48
  • Everything in the select statement (i.e. `Name = rd.Name, ImageUrl = rd.ImageUrl, ResortDetails = rd.ResortDetails,CheckIn = ra.CheckIn, Address = rd.Address, TotalPrice = ra.TotalPrice`) would represent each of the 10 rows being selected IIUC. So, `resortDetails` is not a collection, just varchar attributes in each row. Again, I'm new at using Linq queries so maybe I'm misunderstanding the query I've derived from [another example](https://stackoverflow.com/questions/21051612/entity-framework-join-3-tables) but I just need to query the database and send the returned rows to the view. – loremIpsum1771 May 07 '18 at 03:56
  • @loremIpsum1771 You said *I'm not sure how I could iterate through the resultsObj attribute*, I guess you mean properties, not attributes, am I right? No you did not got exactly what I meant, but I will rewrite the code today later for you – Mohammed Noureldin May 07 '18 at 08:09
  • Yeah I just was saying that I wasn't sure how I would iterate through each of the rows returned from the query if all 10 were stored in resultsObj. – loremIpsum1771 May 07 '18 at 15:50
  • Thanks for the code, but it looks like you still aren't quite understanding what I was asking. I wasn't saying that the `ResortDetails` attribute should be a collection. All I was trying to do is to figure out how to extract the data from the query results into the viewmodels that I created. In my case, I have a join query, so I would have to bind the query results to two different viewmodels which correspond the tables in the join. This was not covered in the vieo series that you linked to which is why I was asking here. I updated the original post with more details for clarity. – loremIpsum1771 May 09 '18 at 00:54