0

I'm following a YouTube series which teachs ASP.NET MVC. In the tutorial the teacher shows how to make a simple search functionality however in my case it's different.

I have search criteria: Studies (Dropdown), Country (Dropdown), Status (Dropdown) and Keyword (Input).

My question is how do I query the database to show the results depending on the search criteria that was chosen?

To be more clear: If the User has chosen Studies and Country only then the code should use values from Studies and Country to search the respective database column.

Click here for the UI Design

Table: Students

[StudentID]        INT          IDENTITY (1, 1) NOT NULL,
[StudentName]      VARCHAR (50) NOT NULL,
[StudentStudiesID] INT          NOT NULL,
[StudentCountry]   VARCHAR (50) NOT NULL,
[StudentCity]      VARCHAR (50) NOT NULL,
[StudentStatus]    VARCHAR (50) NOT NULL,
CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED ([StudentID] ASC),
CONSTRAINT [FK_Students_Studies] FOREIGN KEY ([StudentStudiesID]) REFERENCES [dbo].[Studies] ([StudiesID])

SearchController.cs

public class SearchController : Controller
{
    public ActionResult Index()
    {

        DatabaseEntitiesModel db = new DatabaseEntitiesModel();

        int Studies;
        int.TryParse(Request.QueryString["Studies"], out Studies);
        var Country = Request.QueryString["Country"];
        var Status = Request.QueryString["Status"];
        var Keyword = Request.QueryString["Keyword"];

        IQueryable <Student> SearchQuery = db.Students;
        List<SearchViewModel> SVM = SearchQuery.Select(x => new SearchViewModel
        {
            StudentID = x.StudentID,
            StudentName = x.StudentName,
            StudentCountry = x.StudentCountry,
            StudentCity = x.StudentCity,
            StudiesName = x.Study.StudiesName,
            StudentStatus = x.StudentStatus
        }).OrderByDescending(x => x.StudentID).ToList();

        return View( SVM );
    }
}
Covert
  • 1
  • 2
  • "having no clue" isn't a clear problem statement. It doesn't tell us what you're trying to achieve, and doesn't tell us what difficulty you're facing or what error you're encountering. You clearly have _some_ clue or you wouldn't have written any code. We don't know what your requirements are or what part of them you're stuck with. Please edit your question to be more specific. Thankyou. – ADyson May 09 '18 at 20:53
  • 1
    @ADyson I have edited the question to be more clear. – Covert May 09 '18 at 21:04

2 Answers2

1

Reuse SearchQuery (items are lazy-loaded, until you call ToList()) and add as many specific Where() clauses/calls as you need:

// the type (IQueryable<Student>) should be defined explicitly
// details: https://stackoverflow.com/questions/21969154/cannot-implicitly-convert-type-system-linq-iqueryable-to-system-data-entity-d
IQueryable<Student> query = db.Students;

if(viewModel.Filter1 != null) {
    query = query.Where(i => i.SomeStudentProperty1 == viewModel.Filter1);
}

if(viewModel.Filter2 != null) {
    query = query.Where(i => i.SomeStudentProperty2 == viewModel.Filter2);
}

var result = query.ToList();
lexeme
  • 2,915
  • 10
  • 60
  • 125
  • Thanks for your help. I'm getting an error. `Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Entity.DbSet'. An explicit conversion exists (are you missing a cast?` – Covert May 09 '18 at 21:37
  • @Covert my bad, probably this is due to query type decalartion - I should have declared it as `IQueryable query = db.Students;`. I updated the answer. Here's an [explanation](https://stackoverflow.com/questions/21969154/cannot-implicitly-convert-type-system-linq-iqueryable-to-system-data-entity-d) – lexeme May 10 '18 at 06:37
-1

The easiest way to do this would be to test each condition and if it meets what you want, add a Where clause. Something like this:

 int.TryParse(Request.QueryString["Studies"], out Studies);
 var Country = Request.QueryString["Country"];
 var Status = Request.QueryString["Status"];
 var Keyword = Request.QueryString["Keyword"];

 IQueryable<Student> SearchQuery = db.Students;

 if(Studies > 0)
 {
    SearchQuery = SearchQuery.Where(s => s.StudiesID == Studies);
 }
 if(!string.IsNullOrEmpty(Country))
 {
    SearchQuery = SearchQuery.Where(s => s.StudentCountry == Country);
 }
 ...More conditions can go here

Because of Lazy Loading, the actual query isn't executed until you call .ToList(), or iterate over the collection. Hopefully, this gets you started on the right track.

Edit

In my haste, I changed your IQueryable to a var. Fixed. Also, as Erik pointed out, using Request.QueryString is not the way to go. You'll instead want to pass these values in to the action method. So, something like:

public ActionResult Index(int studies, string status, string country, string keyword)

Matt M
  • 3,699
  • 5
  • 48
  • 76
  • 1
    Request.QueryString[] is very bad practice when using asp.net-mvc. – Erik Philips May 09 '18 at 21:08
  • Thanks for your help. I'm getting an error. `Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Entity.DbSet'. An explicit conversion exists (are you missing a cast?` – Covert May 09 '18 at 21:37
  • 1
    @ErikPhilips Agreed. I took that from the OP's question. Shouldn't your comment be on the question? – Matt M May 09 '18 at 22:05