C# Create employee. Save to SQL Database using EF - c#

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();

Related

Null on updated fields

I am trying to update one single field in a table but it's giving me an error saying that the other content is null. I'm trying to update one single field from a table and leave the other fields as they were.
Code so far:
var user = new User() { CardNumber = cardNumber };
using (var db = new Entities())
{
db.Users.Attach(user);
db.Entry(user).Property(x => x.CardNumber).IsModified = true;
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}
Here is a code example to update the card number and save it.
using (var db = new Entities())
{
User user = db.Users.Where(u => u.Id == userIdToBeUpdated).FirstOrDefault();
user.CardNumber = cardNumber;
db.SaveChanges();
}

Enter new data in db (EF)

I have method in controller
It receive data from post request and write to table
Here is code
[ResponseType(typeof(TimeTable))]
public IHttpActionResult PostTimeTable(TimeTable timeTable)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (ModelState.IsValid)
{
DateTime dt = DateTime.Today;
TimeTable c = (from x in db.TimeTables
where x.Company == timeTable.Company && x.INN == timeTable.INN
select x).First();
c.StartPause = timeTable.StartPause;
c.StartDay = timeTable.StartDay;
c.EndPause = timeTable.EndPause;
c.EndDay = timeTable.EndDay;
db.SaveChanges();
}
db.TimeTables.Add(timeTable);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = timeTable.Id }, timeTable);
}
But it works well when record with INN and Company already in db.
But if it not in database I need to create new entry.
How I need to modify this method?
You can use a flag (exisingCompanyFlag) for edit mode or add new mode like this
bool existingCompanyFlag = true;
TimeTable c = (from x in db.TimeTables
where x.Company == timeTable.Company && x.INN == timeTable.INN
select x).FirstOrDefult();
if (c == null)
{
existingCompanyFlag = false;
c = new TimeTable();
}
c.StartPause = timeTable.StartPause;
c.StartDay = timeTable.StartDay;
c.EndPause = timeTable.EndPause;
c.EndDay = timeTable.EndDay;
if (!existingCompanyFlag)
db.TimeTables.Add(c);
You need a separate branch in your code for the insert case.
if (ModelState.IsValid) {
if (addingNewRow) {
TimeTable tt = new TimeTable {
// Populate properties (except identity columns)
};
db.TimeTables.Add(tt);
} else {
// update
}
db.SaveChanges();
}
To link to other entities use one of:
Assign instances:
x.Company = theCompany;
or, assign the instance id
x.CompanyId = companyId;
(#1 is easier if you already have the other entity loaded or are creating it – EF will sort out the ids – while #2 saves loading the whole other entity.)

Insert data into database using LINQ

I wrote a very simple method. It saves data from class DayWeather to the database. Method checks if line with that day exist in table and update her or create a new line.
I am doing it by adding new class for LINQ and move table from Server Inspector to the constructor. It generate new class WeatherTBL.
Method itself looks like this:
public static void SaveDayWeather(DayWeather day)
{
using (DataClassesDataContext db = new DataClassesDataContext())
{
var existingDay =
(from d in db.WeatherTBL
where d.DateTime.ToString() == day.Date.ToString()
select d).SingleOrDefault<WeatherTBL>();
if (existingDay != null)
{
existingDay.Temp = day.Temp;
existingDay.WindSpeed = day.WindSpeed;
existingDay.Pressure = day.Pressure;
existingDay.Humidity = day.Humidity;
existingDay.Cloudiness = day.Cloudiness;
existingDay.TypeRecip = day.TypeRecip;
db.SubmitChanges();
}
else
{
WeatherTBL newDay = new WeatherTBL();
newDay.DateTime = day.Date;
newDay.Temp = day.Temp;
newDay.WindSpeed = day.WindSpeed;
newDay.Pressure = day.Pressure;
newDay.Humidity = day.Humidity;
newDay.Cloudiness = day.Cloudiness;
newDay.TypeRecip = day.TypeRecip;
db.WeatherTBL.InsertOnSubmit(newDay);
db.SubmitChanges();
}
}
}
When I tried to call him from UnitTest project:
[TestMethod]
public void TestDataAccess()
{
DayWeather day = new DayWeather(DateTime.Now);
DataAccessClass.SaveDayWeather(day);
}
It write, that test has passed successfully. But if look into table, it has`t chanched.
No error messages shows. Does anyone know whats the problem?
P.S. Sorry for my bad English.
UDP
Problem was in that:
"...db maybe copied to the debug or release folder at every build, overwriting your modified one". Thanks #Silvermind
I wrote simple method to save employee details into Database.
private void AddNewEmployee()
{
using (DataContext objDataContext = new DataContext())
{
Employee objEmp = new Employee();
// fields to be insert
objEmp.EmployeeName = "John";
objEmp.EmployeeAge = 21;
objEmp.EmployeeDesc = "Designer";
objEmp.EmployeeAddress = "Northampton";
objDataContext.Employees.InsertOnSubmit(objEmp);
// executes the commands to implement the changes to the database
objDataContext.SubmitChanges();
}
}
Please try with lambda expression. In your code, var existingDay is of type IQueryable
In order to insert or update, you need a variable var existingDay of WeatherTBL type.
Hence try using below..
var existingDay =
db.WeatherTBL.SingleOrDefault(d => d.DateTime.Equals(day.Date.ToString()));
if(existingDay != null)
{
//so on...
}
Hope it should work..
Linq to SQL
Detail tc = new Detail();
tc.Name = txtName.Text;
tc.Contact = "92"+txtMobile.Text;
tc.Segment = txtSegment.Text;
var datetime = DateTime.Now;
tc.Datetime = datetime;
tc.RaisedBy = Global.Username;
dc.Details.InsertOnSubmit(tc);
try
{
dc.SubmitChanges();
MessageBox.Show("Record inserted successfully!");
txtName.Text = "";
txtSegment.Text = "";
txtMobile.Text = "";
}
catch (Exception ex)
{
MessageBox.Show("Record inserted Failed!");
}

LINQ Returning a set of results

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.

C# Trouble updating record with LINQ

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();

Categories