tags:

views:

109

answers:

2

Hello,

I'm using the code below for my search logic, basically, it evaluates a field when there's an input on the corresponding textbox or dropdown, my problem is that the code is only for exact matches, what's the best way to implement also a .Contains() search, or a search which implement an SQL LIKE search?

private void btnSearch_Click(object sender, EventArgs e)
    {            
        bool ok_username = !txtUsername.IsBlank();
        bool ok_firstname = !txtFirstname.IsBlank();
        bool ok_lastname = !txtLastName.IsBlank();
        bool ok_userlevels = cboUserLevels.IsItemInList();

        _query = from _v
                 in Classes.Data.getdb().vUsers
                 where
                   _v.username ==(ok_username ? txtUsername.Text : _v.username) &&
                   _v.firstname == (ok_firstname ? txtFirstname.Text : _v.firstname) &&
                   _v.lastname == (ok_lastname ? txtLastName.Text : _v.lastname) &&
                   _v.userlevel == (ok_userlevels ? cboUserLevels.Text : _v.userlevel)
                 select _v;
        gv.DataSource = _query ;


    }

When i try to enclose the eval expression in a .Contains() function, it says that only expressions which can be evaluated on the client can be used as an argument in a .Contains function. Thanks! Appreciate any advise!


Ok,

Thanks to Alex for giving me an idea about the SQLMethods function. But for now i'll go with Sander's suggestion of chaining expression trees. If anyone can make this code shorter i'll really appreciate it, because in this solution i have two sets of queries one is for the flexible, another is for the exact search. Thanks again to Alex and Sander!

private void btnSearch_Click(object sender, EventArgs e)
    {            

        bool ok_username = !txtUsername.IsBlank();
        bool ok_firstname = !txtFirstname.IsBlank();
        bool ok_lastname = !txtLastName.IsBlank();
        bool ok_userlevels = cboUserLevels.IsItemInList();

        if (optMode.CheckedIndex == 0) //flexible search, the else part is the exact search 
        {
            _query = (from _v
                      in Classes.Data.getdb().vUsers
                      where
                      _v.userlevel == (ok_userlevels ? cboUserLevels.Text : _v.userlevel)
                      select _v);

            if (ok_username)
                _query = _query.Where(x => x.username.Contains(txtUsername.Text));

            if (ok_firstname)
                _query = _query.Where(x => x.firstname.Contains(txtFirstname.Text));

            if (ok_lastname)
                _query = _query.Where(x => x.lastname.Contains(txtLastName.Text));
        }
        else
        {
            _query = (from _v
                      in Classes.Data.getdb().vUsers
                      where
                       _v.username == (ok_username ? txtUsername.Text : _v.username) &&
                       _v.firstname == (ok_firstname ? txtFirstname.Text : _v.firstname) &&
                       _v.lastname == (ok_lastname ? txtLastName.Text : _v.lastname) &&
                       _v.userlevel == (ok_userlevels ? cboUserLevels.Text : _v.userlevel)
                      select _v);
        }

        gv.DataSource = _query.ToList();



    }
A: 

You can make the query more specific step by step like this:

var _query = from _v in Classes.Data.getdb().vUsers
             select v;

if(!txtUsername.IsBlank())
    _query = _query.Where(x => x.username.Contains(txtUsername.Text));

if(!txtFirstName.IsBlank())
    _query = _query.Where(x => x.firstname.Contains(txtFirstName.Text));

// etc.

gv.DataSource = _query;
Sander Rijken
+1 That's another great thing about query expressions. Just need to add the Contains() calls here.
Botz3000
-1 this does not suggest neither how to use `Contains` nor how to use SQL Like operator.
Alex Bagnolini
Hello Sander, Thanks for answering, your answer reminded me that we can indeed chain query expressions. Will formulate a solution base on yours and Alex answer.
thepointofwork
@Alex: updated the answer, made a mistake when typing the code
Sander Rijken
+2  A: 

You have to call Contains from the String inside the database:

_query = 
   from _v in Classes.Data.getdb().vUsers
   where
     (txtUsername.IsBlank() || _v.username.Contains(txtUsername.Text)) &&
     (txtFirstname.IsBlank() || _v.firstname.Contains(txtFirstname.Text)) &&
     (txtLastName.IsBlank() || _v.lastname.Contains(txtLastName.Text)) &&
     (!cboUserLevels.IsItemInList() || _v.userlevel.Contains(cboUserLevels.Text))
   select _v;

If you want to use the SQL Like operator, you can use System.Linq.Data.SqlClient.SqlMethods:

_query = 
   from _v in Classes.Data.getdb().vUsers
   where
     SqlMethods.Like(_v.username, "%" + txtUsername.Text + "%") &&
     SqlMethods.Like(_v.firstname, "%" + txtFirstname.Text + "%") &&
     SqlMethods.Like(_v.lastname, "%" + txtLastName.Text + "%") &&
     SqlMethods.Like(_v.userlevel, "%" + cboUserLevels.Text + "%")
   select _v;
Alex Bagnolini
Hello Alex, Thanks for the SQLMethods tip, i dont know that. One question, will that form of concatenation safe from sql injection when it gets translated? I know linq is safe from sql injection, but how about when using that form? Thanks for the help!
thepointofwork