public static bool CheckLogin(string Username, string Password, bool AutoLogin)
{
bool LoginSuccessful;
// Trim inputs and verify lengths
Username = Username.Trim();
Password = Password.Trim().ToLower();
// Get the associated user records
DataClassesDataContext db = new DataClassesDataContext();
var q = (from User in db.tblForumAuthors where User.Username == Username select new
{
User.Password,
User.Salt,
User.Username,
User.Author_ID,
User.User_code,
User.Active,
User.Login_attempt,
User.Last_visit,
}).SingleOrDefault();
// Invalid details passed
if (q == null)
{
LoginSuccessful = false;
}
else
{
// Increment login attempts counter
int LoginAttempts = q.Login_attempt;
LoginAttempts++;
// Encrypt the password
string HashedPassword = GetSha1(Password + q.Salt);
// Check passwords match
if (q.Password == HashedPassword)
{
LoginSuccessful = true;
}
else
{
LoginSuccessful = false;
// Increment login attempts
q.Login_attempt = LoginAttempts;
db.SubmitChanges();
}
}
return LoginSuccessful;
}
}
On the line
q.Login_attempt = LoginAttempts;
I get:
Error 50 Property or indexer 'AnonymousType#1.Login_attempt' cannot be assigned to -- it is read only C:\inetpub\wwwroot\ScirraNew\App_Code\Login.cs 82 17 C:\...\ScirraNew\
Can anyone show me how I can update this counter in the record please?
You need to just select the whole User item if you want to edit it. Get rid of your whole "Select New" clause.
You can't update properties of an anonymous class instance (even if you could that change just would be local and not be related to any User entity in the DB since the anonymous class instance is a new and different object that you are projecting to), you have to select the User entity itself to update.
So instead of:
var q = (from User in db.tblForumAuthors
where User.Username == Username
select new
{
User.Password,
User.Salt,
User.Username,
User.Author_ID,
User.User_code,
User.Active,
User.Login_attempt,
User.Last_visit,
}).SingleOrDefault();
Use:
var q = (from User in db.tblForumAuthors where User.Username == Username select User).SingleOrDefault();
Or in lambda syntax:
var user = db.tblForumAuthors.Where( u => u.UserName == UserName)
.SingleOrDefault();
Related
I recently switched to C# after NodeJS, I am interested in the question, is it possible to beautifully and correctly format a block of this code, to reduce unnecessarily?
var user = userService.GetById(id);
if (user == null)
return null;
var roles = new List<RoleDTO>();
foreach (var u in user.Roles)
{
roles.Add(new RoleDTO
{
Id = u.Role.Id,
Name = u.Role.Name,
Slug = u.Role.Slug
});
}
return new UserDTO
{
Id = user.Id,
Login = user.Login,
Name = user.Name,
Roles = roles
};
Your code is IMHO already quite short. The only additional thing I can think of is replacing the foreach with a LINQ exprssion in the constructor of List<RoleDTO> and not use a variable for it, like so:
var user = userService.GetById(id);
if (user == null)
return null;
return new UserDTO
{
Id = user.Id,
Login = user.Login,
Name = user.Name,
Roles = new List<RoleDTO>
(
from u in user.Roles
select new RoleDTO
{
Id = u.Role.Id,
Name = u.Role.Name,
Slug = u.Role.Slug
}
)
};
I want to create a sign in form and when user write user and pass i want to find the RoleId which can tell us this user should sign in as operator or manager or any thing else but i can't find how to read Roleid from table?
private void btn_sin_Click(object sender, EventArgs e)
{
byte[] b = System.Text.Encoding.UTF8.GetBytes(txt_pass.Text);
System.Security.Cryptography.SHA1 h = System.Security.Cryptography.SHA1.Create();
byte[] hashed = h.ComputeHash(b);
var txtEncrptedPass = Convert.ToBase64String(hashed);
var query = Obj_db.Tbl_Login.Where(s => s.UserName == txt_Username.Text & s.Password == txtEncrptedPass).ToList();
if (query.Count != 0)
{
DataTable dt = new DataTable();
var m =Convert.ToInt32( query.Select(a => a.RoleId.Value).ToList());
if (m==1)
{
Main_form main = new Main_form();
main.Show();
}
}
else
{
MessageBox.Show(" SignIn error! \n username or password entered incorrectly");
}
this code show me cast error!!
You are trying to convert a list to long.
What you should do it to convert a single value using First() or FirstOrDefault().
With out testing it, change this:
var m = Convert.ToInt32(query.Select(a => a.RoleId.Value).ToList());
to
var m = Convert.ToInt32(query.Select(a => a.RoleId.Value).First());
It should solve your issue.
I'm saving an employee to a SQL database. I'm saving Firstname, Lastname, Username and Password. How should I do this to prevent saving more than one identical username?
I've tried this:
private void CreateEmployee()
{
using (var db = new TidrapportDBEntities())
{
var user = (from p
in db.Login
where p.username != null
select p).ToList();
foreach (var vUser in user)
{
if (vUser.username == textBoxUsername.Text)
{
labelSuccessFail.Visible = true;
labelSuccessFail.Text = "Accountname already exist.";
break;
}
else
{
var userInfo = new Login();
var persInfo = new PersonalInformation();
persInfo.firstname = textBoxFirstname.Text;
persInfo.lastname = textBoxLastname.Text;
userInfo.username = textBoxUsername.Text;
userInfo.password = textBoxPassword.Text;
userInfo.employeeId = persInfo.employeeId;
db.Login.Add(userInfo);
db.PersonalInformation.Add(persInfo);
db.SaveChanges();
textBoxFirstname.Text = string.Empty;
textBoxLastname.Text = string.Empty;
textBoxUsername.Text = string.Empty;
textBoxPassword.Text = string.Empty;
labelSuccessFail.Visible = true;
labelSuccessFail.Text = "Successfully created account.";
}
}
}
}
Any tips what I can try?
Kind regards,
Kristian
You should have a unique constraint on the username field. Not sure if you're doing code first, model first or DB first in your EF, but you should be able to google how to get it set on your database using the right method. That will throw an exception if you try to save one, so that makes sure you can't have more than one.
You could also use LINQ statement to restrict the list of users to the user name you wish to create and then you're just down to checking a bool to see if a row is returned or not. That way you're not having to read the entire database table (which your "toList" is doing).
In your code example, you're getting all the users where they have a user name, you're then looping round them, but your conditional code only really works if the first one matches the user name you're trying to save, otherwise you are going to try and recreate a duplicate the second time around. So just to get your code working you could try:
private void CreateEmployee()
{
using (var db = new TidrapportDBEntities())
{
var user = (from p
in db.Login
where p.username != null
select p).ToList();
bool found = false;
foreach (var vUser in user)
{
if (vUser.username == textBoxUsername.Text)
{
found = true;
labelSuccessFail.Visible = true;
labelSuccessFail.Text = "Accountname already exist.";
break;
}
}
if(!found)
{
var userInfo = new Login();
var persInfo = new PersonalInformation();
persInfo.firstname = textBoxFirstname.Text;
persInfo.lastname = textBoxLastname.Text;
userInfo.username = textBoxUsername.Text;
userInfo.password = textBoxPassword.Text;
userInfo.employeeId = persInfo.employeeId;
db.Login.Add(userInfo);
db.PersonalInformation.Add(persInfo);
db.SaveChanges();
i have some code that sets user's properties like so:
us = new UserSession();
us.EmailAddr = emailAddr;
us.FullName = fullName;
us.UserROB = GetUserROB(uprUserName);
us.UserID = GetUserID(uprUserName);
us.UserActive = GetUserActive(uprUserName);
where GetUserROB, GetUserID and GetUserActive all look similar like so:
private static string GetUserActive(string userName)
{
using (Entities ctx = CommonSERT.GetContext())
{
var result = (from ur in ctx.datUserRoles
where ur.AccountName.Equals(userName, StringComparison.CurrentCultureIgnoreCase)
select new
{
Active = ur.active
}).FirstOrDefault();
if (result != null)
return result.Active;
else
return "N";
}
}
it works, but i dont think it's the right way here. how can i assign userROB, ID and Active properties all in one LINQ call? without having to have 3 separate functions to do this?
If I understand correctly I believe you can do something like:
private static void GetUserData(string userName, UserSession userSession)
{
using (Entities ctx = CommonSERT.GetContext())
{
var result = (from ur in ctx.datUserRoles
where ur.AccountName.Equals(userName, StringComparison.CurrentCultureIgnoreCase)
select new
{
UserActive = ur.active,
UserROB = ur.ROB,
UserID = ur.ID
}).FirstOrDefault();
}
if (result != null) {
userSession.UserActive = result.UserActive;
userSession.UserROB = result.UserROB;
userSession.UserID = result.UserID;
}
}
In the select new you can place as many properties as you want, this way you can get from the database several properties in a single roundtrip, and handling it later.
In the example I gave, I pass the UserSession as a parameter, in any case you already have other properites alrealdy filled from other methods.
You can create a method that accepts a UserSession object as parameter, then set all three properties in it. I changed your GetUserActive a bit here:
private static void GetUserData(string userName, UserSession user)
{
using (Entities ctx = CommonSERT.GetContext())
{
var result = (from ur in ctx.datUserRoles
where ur.AccountName.Equals(userName, StringComparison.CurrentCultureIgnoreCase)
select new
{
Active = ur.active,
ID = ur.ID,
//...select all properties from the DB
}).FirstOrDefault();
if (result != null)
user.UserActive = result.Active;
user.UserID = result.ID;
//..set all properties of "user" object
}
}
Well you might consider normalising your domain model and having a User property of type User, then your method would return all of the related user data.
I have a bunch of Linq to Entity methods that had the same select statement, so I thought I would be clever and separate that out into it's own method to reduce redundancy... but when i attempted to run the code, i got the following error...
this method cannot be translated into
a store expression
Here is the method i created...
public User GetUser(DbUser user, long uid)
{
return new User
{
Uid = user.uid,
FirstName = user.first_name,
LastName = user.last_name
};
}
And am calling in a method like this...
public User GetUser(long uid)
{
using (var entities = new myEntities()) {
return
entities.DbUsers.Where( x => x.uid == uid && x.account_status == ( short )AccountStatus.Active ).
Select( x => GetUser( x, uid ) ).FirstOrDefault( );
}
}
UPDATE: here is the code that works inline
public User GetUser(long uid, long uid_user)
{
using (var entities = new myEntities())
{
var q = from u in entities.DbUsers
where u.uid == uid_user
select new User
{
Uid = u.uid,
FirstName = u.first_name,
LastName = u.last_name,
BigPicUrl = u.pic_big,
Birthday = u.birthday,
SmallPicUrl = u.pic_small,
SquarePicUrl = u.pic_square,
Locale = u.locale.Trim(),
IsFavorite = u.FavoriteFriends1.Any(x => x.uid == uid),
FavoriteFriendCount = u.FavoriteFriends.Count,
LastWishlistUpdate = u.WishListItems.OrderByDescending(x => x.added).FirstOrDefault().added,
Sex = (UserSex)u.sex
};
var user = q.FirstOrDefault();
user.DaysUntilBirthday = user.Birthday.DaysUntilBirthday();
return user;
}
}
The error is spot on, you can't translate that into a T-SQL (or P-SQL) query.
You need to make sure you've executed the query before you attempt to hydrate it into some other type.
Keep it simple, use an extension method. That's what they are there for.
public static User ToUserEntity(this DbUser user)
{
return new User
{
Uid = user.uid,
FirstName = user.first_name,
LastName = user.last_name
};
}
Then in your DAL:
public User GetUser(long uid)
{
User dbUser;
using (var entities = new myEntities())
{
dbUser = entities.DbUsers
.Where( x => x.uid == uid && x.account_status == (short)AccountStatus.Active )
.FirstOrDefault(); // query executed against DB
}
return dbUser.ToUserEntity();
}
See how i hydrate the POCO into an object after the context has been disposed? This way, you ensure EF has finished it's expression work before you attempt to hydrate into a custom object.
Also i dont know why you're passing uid to that method, it's not even being used.
On a further note, you shouldn't need to do this kind of thing (project EF POCO's into your own objects).
If you do, it's a good case for custom POCO's (map the tables straight into your custom POCO's, don't use the Code Generation).
This expression will work to give the desired result (somewhat) I still havent figured out how to pass in additional variables in teh select statements...
..... .Select(GetUser).FirstOrDefault()
static readonly Expression<Func<DbUser, User>> GetUser = (g) => new User {
Uid = g.uid,
FirstName = g.first_name,
LastName = g.last_name,
BigPicUrl = g.pic_big,
Birthday = g.birthday,
SmallPicUrl = g.pic_small,
SquarePicUrl = g.pic_square,
Locale = g.locale.Trim(),
//IsFavorite = g.FavoriteFriends1.Any(x=>x.uid==uid),
FavoriteFriendCount = g.FavoriteFriends.Count,
LastWishlistUpdate = g.WishListItems.OrderByDescending( x=>x.added ).FirstOrDefault().added
};
You can't do this because the getUser method cannot be converted to any TSQL statement.
if you return your DBUser first and then use it as the first parameter of the GetUser method then you are forcing it to execute and once you have you DBUser you can pass it to GetUser
Maybe you can try this:
public User GetUser(long uid)
{
using (var entities = new myEntities())
{
return GetUser(
entities.DbUsers
.Where( x => x.uid == uid && x.account_status == (short)AccountStatus.Active )
.FirstOrDefault(),
uid);
}
}
EDIT
Since you are saying it still fails could it be beacuse of the enum??
public User GetUser(long uid)
{
using (var entities = new myEntities())
{
short status = (short)AccountStatus.Active;
return GetUser(
entities.DbUsers
.Where( x => x.uid == uid && x.account_status == status )
.FirstOrDefault(),
uid);
}
}