0

Can you teach me more about how does this linq code work? string pass = HashPassword(password) is a string, HashPassword(password) returns a string too.

But the LinQ needs a variable to store the string before comparing. Like this:

public bool Login(string email, string password)
        {
            try
            {
                string pass = HashPassword(password);
                var acc = db.UserAccount.SingleOrDefault(x => x.Email == email && x.HashPassword == pass);
                if (acc != null)
                {
                    return true;
                }
                // email or password is not matched
                return false;
            }
            catch { return false; }
        }

and the method to hash password:

private string HashPassword(string password)
{
    return BitConverter.ToString(new SHA256CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(password))).Replace("-", "");
}

Since I changed the line var acc = db.UserAccount.SingleOrDefault(x => x.Email == email && x.HashPassword == pass);

to

var acc = db.UserAccount.SingleOrDefault(x => x.Email == email && x.HashPassword == HashPassword(password));

It wouldn't work. Why?

  • What is the error you are receiving? – Shelby115 Sep 01 '15 at 17:48
  • @Shelby115 in linq line, if I replace `pass` to `HashPassword(password)`, it will always return false. –  Sep 01 '15 at 17:50
  • 3
    @Kevin if you use something other than Linq2objects, like EF, Linq2DB etc, Linq provider will not be able to translate `HashPassword(password)` to a sql code(it can not be converted to a sql stmt). Your first version is just a simple string comparison (`WHERE EMAiL=@SOMEVAR`). – Eser Sep 01 '15 at 17:53
  • 1
    So, it's returning false, not actually erroring? – Cory Sep 01 '15 at 17:53
  • 1
    Place a break-point on your catch statement and it'll tell you why it is returning false every time. – Shelby115 Sep 01 '15 at 17:54
  • @Shelby115 Yes. It will turn to `catch` statement without `if (acc != null) {}`. Why? –  Sep 01 '15 at 17:57
  • @Cory I don't understand that: Why didn't it return `true`? I'm sure that `email` and `password` were correct –  Sep 01 '15 at 17:59
  • 1
    Because of what @Eser said: the LINQ provider can't translate your HashPassword function. The exception you get will have a message to that effect. – Jerry Federspiel Sep 01 '15 at 17:59

1 Answers1

0

Your statement: var acc = db.UserAccount.SingleOrDefault(x => x.Email == email && x.HashPassword == HashPassword(password)); is causing an exception and jumping to the catch-statement. Below is the reason why.

Effectively LINQ doesn't know how to handle your function and the reason why it works with just x.HashPassword == pass is because that's just a simple string comparison.

Excerpt from similar Q&A

LINQ 2 SQL is converting your query into an expression tree, and then translating that expression tree into SQL. Since your custom function doesn't have an SQL correlated function, it doesn't know how to translate it and throws an exception. - David Pfeffer

Community
  • 1
  • 1
Shelby115
  • 2,816
  • 3
  • 36
  • 52