Linq-to-SQL seeing if the are no results - c#

How come my code is showing a syntax error on this block of code
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).First();
if (password == 0)
{ }
return password;
}
I want to know if the result of query is 0, if it is 0 I will close the operation or something like that. but It keeps showing an error how would I know if the result is 0? also if you have suggestions regarding my approach feel free to put it in

Calling .First() will result in an exception if there is no data returned...
Calling .FirstOrDefault() will return null if there is no data
public string getPassword()
{
DataClasses1DataContext myDbContext = new DataClasses1DataContext(dbPath);
var password = (from user in myDbContext.Accounts
where user.accnt_User == txtUser.Text
select user.accnt_Pass).FirstOrDefault();
if (password == null)
{
// no data found - do whatever is needed in that case...
}
return password;
}

Related

Else statement never reach

i have an if statements align with a query in Linq to create the login in my app, but, the code works bad, when the query don't select any record, the .Count() it's equal to zero and it have sense, but in the if, the code never reach the else part, look, this is my code:
var UserLogin = from m in _context.User where m.Username.Contains(this.Username) & m.Password.Contains(this.Password) select m.Username;
this.Username = string.Empty;
this.Password = string.Empty;
if(UserLogin.Count() != 0)
{
//HttpContext.Session.SetString("Username", UserLogin.First());
UsernameLogged = UserLogin.First();
}
else
{
Console.WriteLine("Sisa: " + UsernameLogged);
this.Username = string.Empty;
this.Password = string.Empty;
UsernameLogged = string.Empty;
Console.WriteLine(UsernameLogged);
}
Note that the query is executed twice. The first time when you call UserLogin.Count(). The second time when you call UserLogin.First(). But then, you already have set Username and Password to string.Empty and all the user names and passwords do contain an empty string because String.Contains tests only whether a part of the string matches. So you are getting all the users in the result. Use == to test the whole string.
Since you want to get only one user, use FirstOrDefault which returns null when no user was found.
var userLogged = _context.User
.FirstOrDefault(u => u.Username == Username && u.Password == Password);
if (userLogged is null) {
Console.WriteLine("Sisa: " + UsernameLogged);
Username = string.Empty;
Password = string.Empty;
UsernameLogged = string.Empty;
Console.WriteLine(UsernameLogged);
} else {
UsernameLogged = userLogged.Username;
}
You are setting Username and Password to string.Empty twice. Either clear them after the if-else if you always want to do so, or do it only when no user was found.
This is because of you are using deferred execution of LINQ query. Your query is executed in if condition and there you will get count 1.
Use below code -
var UserLogin = from m in _context.User where m.Username.Contains(this.Username) & m.Password.Contains(this.Password) select m.Username;
var count = UserLogin.Count(); // Here your query will be execute
this.Username = string.Empty;
this.Password = string.Empty;
if(count != 0)
{
//HttpContext.Session.SetString("Username", UserLogin.First());
UsernameLogged = UserLogin.First();
}
else
{
Console.WriteLine("Sisa: " + UsernameLogged);
this.Username = string.Empty;
this.Password = string.Empty;
UsernameLogged = string.Empty;
Console.WriteLine(UsernameLogged);
}
This will execute your else condition.

MembershipUser not getting updated result from database

I'm building a simple application where a user can edit their profile including adding/deleting a brand image. This seems to be working fine and is updating the database no problem, however when refreshing the page and retrieving the user details via Membership.GetUser() the result includes the old results and not those from the updated database.
Here is my MembershipUser GetUser override:
public override MembershipUser GetUser(string query, bool userIsOnline)
{
if (string.IsNullOrEmpty(query))
return null;
var db = (AccountUser)null;
// ...get data from db
if (query.Contains("#")){
db = _repository.GetByQuery(x => x.Email == query).FirstOrDefault();
}
else
{
string firstName = query;
string lastName = null;
if (query.Contains(" "))
{
string[] names = query.Split(null);
firstName = names[0];
lastName = names[1];
}
// ...get data from db
db = _repository.GetByQuery(x => x.FirstName == firstName && x.LastName == lastName).FirstOrDefault();
}
if (db == null)
return null;
ToMembershipUser user = new ToMembershipUser(
"AccountUserMembershipProvider",
db.FirstName + " " + db.LastName,
db.ID,
db.Email,
"",
"",
true,
false,
TimeStamp.ConvertToDateTime(db.CreatedAt),
DateTime.MinValue,
DateTime.MinValue,
DateTime.MinValue,
DateTime.MinValue);
// Fill additional properties
user.ID = db.ID;
user.Email = db.Email;
user.FirstName = db.FirstName;
user.LastName = db.LastName;
user.Password = db.Password;
user.MediaID = db.MediaID;
user.Media = db.Media;
user.Identity = db.Identity;
user.CreatedAt = db.CreatedAt;
user.UpdatedAt = db.UpdatedAt;
return user;
}
Note I am using a custom MembershipProvider and MembershipUser. Here is where I am calling that method:
public ActionResult Edit()
{
ToMembershipUser toUser = Membership.GetUser(User.Identity.Name, true) as ToMembershipUser;
Now when I do a separate query just under this line of code straight to the database, not invoking MembershipUser, I get the updated result which in turn updates the MembershipUser result?!
It seems it may be caching the results? Anyway around this? I hope this is clear enough. Thanks
Edit:
It appears that when I set a breakpoint just after :
// ...get data from db
db = _repository.GetByQuery(x => x.FirstName == firstName && x.LastName == lastName).FirstOrDefault();
'db' retrieves the outdated results though surely this is talking to the database? If need be I'll update with my repository pattern
I managed to find a workaround though I'm not happy with this solution, so if anyone can improve upon this please post.
I decided to manually update the MembershipUser instance manually each time I update the image. My controller now looks like this:
private static ToMembershipUser MembershipUser { get; set; }
// GET: Dashboard/AccountUsers/Edit
public ActionResult Edit()
{
if(MembershipUser == null)
MembershipUser = Membership.GetUser(User.Identity.Name, true) as ToMembershipUser;
}
[HttpPost]
[ValidateJsonAntiForgeryToken]
public JsonResult UploadMedia(IEnumerable<HttpPostedFileBase> files, int id)
{
var images = new MediaController().Upload(files);
if (images == null)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json("File failed to upload.");
}
AccountUser accountUser = db.AccountUsers.Find(id);
db.Entry(accountUser).State = EntityState.Modified;
accountUser.UpdatedAt = TimeStamp.Now();
accountUser.MediaID = images[0];
db.SaveChanges();
MembershipUser.Media = accountUser.Media;
MembershipUser.MediaID = accountUser.MediaID;
return Json(new { result = images[0] });
}
[HttpPost]
[ValidateJsonAntiForgeryToken]
public JsonResult DeleteMedia(int id)
{
bool delete = new MediaController().Delete(id, 1);
if (!delete)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json("Error. Could not delete file.");
}
MembershipUser.Media = null;
MembershipUser.MediaID = null;
return Json("Success");
}

How to pass a variable to another namespace?

I have to pass a count value to another namespace here. I have 2 classes Select.cs and Value.cs. Select.cs has the following code:
public bool Login(string UserName, string Password)
{
string strinvselect = string.Format("select * from newlog where
pass='{0}'", Password);
DataTable dtlog = ExecuteStatement(strinvselect);
if (dtlog.Rows.Count == 1)
{
string strvalue = string.Format("Select * FROM login WHERE uid=
'{0}'", UserName);
DataTable newlogin = ExecuteStatement(strvalue);
try
{
if (newlogin.Rows.Count == 1)
{
loginStatus = true;
}
}
catch (Exception ex)
{
loginStatus = false;
}
return loginStatus;
}
}
I have to create a count value if(newlogin.Rows.Count == 1), count=1 and this value should be available in Value.cs to check a functionality.
In Value.cs a function getdetails() is called. Here I need to check
if (count == 1)
{
getdetails();
}
else
{
// call another function
}
I found the answer:
Namespaces are not really relevant here, the issue is that you need to access the variable from a different class. The way you have "global" variables that are specific to the user is the Session, so store the value in a Session variable and have your other class access the Session variable.
HttpContext.Current.Session["myData"] = "somevalue";
Value function
string x;
if (Session["myData"] == null)
{
// handle the data not being set
}
else
{
x = (string)HttpContext.Current.Session["myData"].ToString(); ;
}
You can check for query for count outside Login ( basically wherever you need it ) then pass it as "username + count" (you will need to split it) to login first parameter as you can avoid checking count inside Login again.

Calling get method using linq query?

I am trying to call the following get method in web api but I am currently experiencing an compiling error - 'bool' does not contain a definition for 'password' and no extension method 'password' accepting a first argument of type 'bool' could be found (are you missing a using directive or an assembly reference?) -- error
User class:
public class User : iUser
{
private cdwEntities db;
public User()
{
db = new cdwEntities();
}
public User(cdwEntities context)
{
db = context;
}
public bool Validate(string username, string password)
{
var query = from t in db.Trial_Try
join u in db.UserDetails on t.tUID equals u.uID
where t.tExpiryDate >= DateTime.Now &&
t.tPublication.Value == 163 &&
u.uUsername == username &&
u.uPassword == password
select u; //
// "execute" the query
return query.FirstOrDefault() != null;
}
Test class:
public HttpResponseMessage GetValidate(string username, string password)
{
User layer = new User();
var result = layer.Validate(username, password);
***if (result.username != null && result.password != null)***
{
var mes = string.Format("Success");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, mes);
}
else
{
//var mis = string.Format("User {0} not found");
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, mis, result);
return null;
}
}
Validate is returning a Boolean, not the result of the query. As #ekad stated, check result as a Boolean directly.
As an additional optimization, consider using .Any instead of FirstOrDefault since you don't need the hydrated result and can optimize the SQL to an Exists query rather than select top 1. Your validate method could then be:
public bool Validate(string username, string password)
{
var query = from t in db.Trial_Try
join u in db.UserDetails on t.tUID equals u.uID
where t.tExpiryDate >= DateTime.Now &&
t.tPublication.Value == 163 &&
u.uUsername == username &&
u.uPassword == password
select u; //
// "execute" the query
return query.Any();
}
The problem is result is a bool and it doesn't have username or password property, so you need to replace this line
if (result.username != null && result.password != null)
with this
if (result)

Not all code paths return a value

I get an error not all code paths return a value?
public string Authentication(string studentID, string password) // this line?
{
var result = students.FirstOrDefault(n => n.StudentID == studentID);
//find the StudentID that matches the string studentID
if (result != null)
//if result matches then do this
{
//----------------------------------------------------------------------------
byte[] passwordHash = Hash(password, result.Salt);
string HashedPassword = Convert.ToBase64String(passwordHash);
//----------------------------------------------------------------------------
// take the specific students salt and generate hash/salt for string password (same way student.Passowrd was created)
if (HashedPassword == result.Password)
//check if the HashedPassword (string password) matches the stored student.Password
{
return result.StudentID;
// if it does return the Students ID
}
}
else
//else return a message saying login failed
{
return "Login Failed";
}
}
if the result is not null but the result.Password != HashedPassword you're not returning anything.
You should change to something like:
...
if (HashedPassword == result.Password)
{
return result.StudentID;
// if it does return the Students ID
}
return "Invalid Password";
...
The problem is that your first if statement doesn't ensure the returning of a value, due to the nested if statement. Imagine you have result set to a value (not null) and your hashed password and supplied password do not match, if you follow that logic through you will fail to hit a return statement.
You should either add an else clause to your nested if statement like so:
if (HashedPassword == result.Password)
//check if the HashedPassword (string password) matches the stored student.Password
{
return result.StudentID;
// if it does return the Students ID
}
else
{
return "Login Failed";
}
or more desirably, remove the else statement you already have so the function ends with returning the login failed:
if (result != null)
{
//....
}
return "Login Failed";
...with this second approach you do no need to worry about using the else because if all your other conditions are satisfied, the nested return statement will end the function anyway. Try to think of this final return as the default action if any of the authentication steps fail
Another note to make on your code is that it is not ideal practise to be returning a mix of data in such a way. i.e. the result could be a student ID or it could be an error message. Consider creating a dedicated result class with multiple properties that the calling code can check to see the status of the logic validation. A class something like the following would be a good start:
public class LoginResult
{
//determines if the login was successful
public bool Success {get;set;}
//the ID of the student, perhaps an int datatype would be better?
public string StudentID {get;set;}
//the error message (provided the login failed)
public string ErrorMessage {get;set;}
}
(saying all that though, your calling code already appears to be aware of the studentID anyway)
remove the else. Just do
if(result != null) {
...
}
return "Login Failed";
you should also return something in case of:
if (HashedPassword != result.Password)
put an else in the inner if
i have made some changes in your code. try it.
public string Authentication(string studentID, string password)
{
var result = students.FirstOrDefault(n => n.StudentID == studentID);
var yourVar;
if (result != null)
{
byte[] passwordHash = Hash(password, result.Salt);
string HashedPassword = Convert.ToBase64String(passwordHash);
if (HashedPassword == result.Password)
{
//return result.StudentID;
yourVar = result.StudenID;
// if it does return the Students ID
}
}
else
//else return a message saying login failed
{
yourVar = "Login Failed";
}
return yourVar;
}

Categories