Failed to enable constraints using TableAdapters - c#

I'm trying to check if a username exists in my table when everytime a character is entered in the TextBox. Here is my code:
Within the register.aspx.cs file I have a TextChanged event on the TextBox:
protected void username_txt_TextChanged(object sender, EventArgs e)
{
string check = authentication.checkUsername(username_txt.Text);
if(check == "false")
{
username_lbl.Text = "Available";
}
else
{
username_lbl.Text = "Not Available";
}
}
It calls this method:
public static string checkUsername(string Username)
{
userInfoTableAdapters.usersTableAdapter userInfoTableAdapters = new userInfoTableAdapters.usersTableAdapter();
DataTable userDataTable = userInfoTableAdapters.checkUsername(Username);
DataRow row = userDataTable.Rows[0];
int rowValue = System.Convert.ToInt16(row["Users"]);
if (rowValue == 0)
{
return "false";
}
else
{
return "true";
}
}
The query that is being executed is:
SELECT COUNT(username) AS Users FROM users WHERE (username = #Username)
For some reason, it keeps breaking on this line:
DataTable userDataTable = userInfoTableAdapters.checkUsername(Username);
It gives an error that says:
Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
Just incase, the username field in my table is Unique and Not Null, I have tried just executing the query itself and it works perfectly so it isn't at the query end.
Does anyone understand what I am doing wrong?

Your query doesn't return the row - so using a TableAdapter query that returns the DataTable is inappropriate in this case.
I'd recommend using your query with something like the function below. I took the liberty of actually returning boolean....
public static bool checkUsername(string userName)
{
SqlClient.SqlCommand withCmd = new SqlClient.SqlCommand();
bool result = false;
withCmd.Connection.Open();
withCmd.CommandType = CommandType.text;
withCmd.CommandText = "SELECT COUNT(username) AS Users FROM users WHERE (username = #Username)"
withCmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("#Username", System.Data.SqlDbType.VarChar, 16)).Value = userName;
try {
int intResult;
object scalarResult = withCmd.ExecuteScalar();
if ((scalarResult != DBNull.Value)
&& (scalarResult != null)
&& (int.TryParse(scalarResult, out intResult)))
result = (intResult==1);
} catch (Exception ex) {
result = false; // hmm, bad...can't tell handle error...
} finally {
// only close if we opened the connection above ...
withCmd.Connection.Close();
}
}
return result;
}
A TableAdapter does support scalar queries on the Table Object, when you add and name your query, check the properties of that query and be sure its ExecuteMode is Scalar. It will then return the integer value, not the row!
On the other hand, if you want to keep your structure, change the query to actually return the row, something like
SELECT uu.* AS dbo.Users uu FROM users WHERE (username = #Username)
and make the result of the checkUsername() function depend on the number of rows returned (which should be 1 or zero....)

Related

Find the null value of a Datatable

I am building a AWS lambda function .net core.
The issue I am encountering is, when there is no data in the row / column of the datatable I still get a count of one, in turn getData != null && getData.Count() > 0 defaults true and then throws a NullRefrenceError since the value is null when it goes to the loop, I have tried checking for multiple null types in datatable with them still defaulting to true.
Is there another way to check for nullable values, to avoid the assignment causing the error in a datatable column / row.
public object emailGets ( AType invoiceNum, ILambdaContext context )
{
Connection conn = new Connection();
try
{
string query = "SELECT QUERY";
conn.getData(query);
DataRow[] getData = conn.Dt.Select();
if(getData != null && getData.Count() > 0)
{
foreach (var item in getData)
{
string yourItem = item.Field<String>("email").ToString();
}
return new userData { email = yourItem};
}
else
{
return new userEmailAddress { email = null};
}
} catch ( Exception e )
{
throw e;
}
}
}
public class userEmailAddress
{
public string email { get; set; }
}
ToString() will throw a NullReferenceException when the source is null. So when you do
string yourItem = item.Field<String>("email").ToString();
and the item.Field<String>("email") part returns null, you'll get that exception.
Luckily, that ToString() call is redundant, so you can simply remove it and just have:
string yourItem = item.Field<String>("email");
Keep in mind that yourItem can now be null here.

Parameter '?user_email' not found in the collection

I am using MySql 5.6x with Visual Studio 2015, windows 10, 64-bit. C# as programming language. In my CRUD.cs (Class file) i have created the following method:
public bool dbQuery(string sql,string[] paramList= null)
{
bool flag = false;
try
{
connect();
cmd = new MySqlCommand(sql,con);
cmd.Prepare();
if(paramList != null){
foreach(string i in paramList){
string[] valus = i.Split(',');
string p = valus[0];
string v = valus[1];
cmd.Parameters[p].Value = v;
}
}
if (cmd.ExecuteNonQuery() > 0)
{
flag = true;
}
}
catch (Exception exc)
{
error(exc);
}
}
I am passing the query and Parameters List like this:
protected void loginBtn_Click(object sender, EventArgs e)
{
string sql = "SELECT * FROM dept_login WHERE (user_email = ?user_email OR user_cell = ?user_cell) AND userkey = ?userkey";
string[] param = new string[] {
"?user_email,"+ userid.Text.ToString(),
"?user_cell,"+ userid.Text.ToString(),
"?userkey,"+ userkey.Text.ToString()
};
if (db.dbQuery(sql, param))
{
msg.Text = "Ok";
}
else
{
msg.Text = "<strong class='text-danger'>Authentication Failed</strong>";
}
}
Now the problem is that after the loop iteration complete, it directly jumps to the catch() Block and generate an Exception that:
Parameter '?user_email' not found in the collection.
Am i doing this correct to send params like that? is there any other way to do the same?
Thanks
EDIT: I think the best way might be the two-dimensional array to collect the parameters and their values and loop then within the method to fetch the parameters in cmd.AddWidthValues()? I may be wrong...
In your dbQuery you don't create the parameters collection with the expected names, so you get the error when you try to set a value for a parameter that doesn't exist
public bool dbQuery(string sql,string[] paramList= null)
{
bool flag = false;
try
{
connect();
cmd = new MySqlCommand(sql,con);
cmd.Prepare();
if(paramList != null){
foreach(string i in paramList){
string[] valus = i.Split(',');
string p = valus[0];
string v = valus[1];
cmd.Parameters.AddWithValue(p, v);
}
}
if (cmd.ExecuteNonQuery() > 0)
flag = true;
}
catch (Exception exc)
{
error(exc);
}
}
Of course this will add every parameter with a datatype equals to a string and thus is very prone to errors if your datatable columns are not of string type
A better approach would be this one
List<MySqlParameter> parameters = new List<MySqlParameter>()
{
{new MySqlParameter()
{
ParameterName = "?user_mail",
MySqlDbType= MySqlDbType.VarChar,
Value = userid.Text
},
{new MySqlParameter()
{
ParameterName = "?user_cell",
MySqlDbType= MySqlDbType.VarChar,
Value = userid.Text
},
{new MySqlParameter()
{
ParameterName = "?userkey",
MySqlDbType = MySqlDbType.VarChar,
Value = userkey.Text
},
}
if (db.dbQuery(sql, parameters))
....
and in dbQuery receive the list adding it to the parameters collection
public bool dbQuery(string sql, List<MySqlParameter> paramList= null)
{
bool flag = false;
try
{
connect();
cmd = new MySqlCommand(sql,con);
cmd.Prepare();
if(paramList != null)
cmd.Parameters.AddRange(paramList.ToArray());
if (cmd.ExecuteNonQuery() > 0)
{
flag = true;
}
}
catch (Exception exc)
{
error(exc);
}
}
By the way, unrelated to your actual problem, but your code doesn't seem to close and dispose the connection. This will lead to very nasty problems to diagnose and fix. Try to use the using statement and avoid a global connection variable
EDIT
As you have noticed the ExecuteNonQuery doesn't work with a SELECT statement, you need to use ExecuteReader and check if you get some return value
using(MySqlDataReader reader = cmd.ExecuteReader())
{
flag = reader.HasRows;
}
This, of course, means that you will get troubles when you want to insert, update or delete record where instead you need the ExecuteNonQuery. Creating a general purpose function to handle different kind of query is very difficult and doesn't worth the work and debug required. Better use some kind of well know ORM software like EntityFramework or Dapper.
Your SQL Commands' Parameters collection does not contain those parameters, so you cannot index them in this manner:
cmd.Parameters[p].Value = v;
You need to add them to the Commands' Parameters collection in this manner: cmd.Parameters.AddWithValue(p, v);.

How to fix a boolean method that returns true everytime asp.net

I designed my webpage to read a data string then display the results on labels in an html table. I am attempting to highlight the row that my database reads as a current order. My only problem is only one record is set to be active but they all highlight as if they were active. I use an array to set my data and I also use the label to get the ID I need (all is in code below). I have posted my method and where I use it in the asp page load. How can I fix my method to return correctly?
The implementing of the method in page load
if (lineData.IsCurrentOrderFind(L68.Text))
{
myTable.Rows[1].Cells[0].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[1].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[2].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[3].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[4].BgColor = "#FE2E2E";
}
Here is method that label above gets passed to
public bool IsCurrentOrderFind(string itemNumber)
{
StringBuilder sqlString = new StringBuilder();
sqlString.Append("SELECT * ");
sqlString.Append("FROM WorkOrder ");
sqlString.Append("WHERE LineNumber = " + ConfigurationManager.AppSettings["Line"] + " AND LineCompleted = 0 AND (ScaleGroup LIKE '%1' OR ScaleGroup LIKE '%3') ");
sqlString.Append(" AND CaseGenNum6 = #CaseGenNum6");
SqlDataReader reader = null;
SqlConnection dbConn = App_Code.DBHelper.getConnection();
SqlParameter[] parameters = new SqlParameter[] { new SqlParameter("#CaseGenNum6", itemNumber) };
try
{
reader = App_Code.DBHelper.executeQuery(dbConn, sqlString.ToString(), parameters);
while (reader.Read())
{
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
reader.Close();
reader.Dispose();
dbConn.Close();
dbConn.Dispose();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (dbConn != null)
{
try { dbConn.Close(); dbConn.Dispose(); }
catch { }
}
if (reader != null)
{
try { reader.Close(); reader.Dispose(); }
catch { }
}
}
if (IsCurrentOrder == true) I realize this is not necessary
{
return true;
}
else
{
return false;
}
}
The problem could be with this expression:
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())
Instead of calling ToString(), try simply casting it to a string:
!string.IsNullOrEmpty((string)reader["IsCurrentOrder"])
Possibly even better (the previous line might throw an exception if it's not really a string):
!string.IsNullOrEmpty(reader["IsCurrentOrder"] as string)
The reason being is that if the string is really null, calling ToString() will return a non-null string "null".
IsCurrentOrder is not declared locally. It seems to be declared at a higher scope. When you enter this function, nothing is initializing the variable (back to false). So, it is remaining at its last setting. Try this code instead:
public bool IsCurrentOrderFind(string itemNumber)
{
bool IsCurrentOrder = false;
//and the rest of your source code
the line
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
It's not actually checking the value of the field, only that it's not null or empty.
Try
if(
(reader["IsCurrentOrder"] != DBNull.Value
&&
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString()))
)
{
IsCurrentOrder = reader["IsCurrentOrder"];
}
else
IsCurrentOrder = false;
I think there is a lot of refactoring you could do to this method though that will simplify the logic.

Querying database comparing cell from Excel file using C#

I am trying to see if this cell in my excel spreadsheet is the PK in the database. I am using Aspose for bring in the excel file (this works). I know the connection string is working as well.
I am wanting to query the database for this code. If this code brings a row back, I want the flag to be true. If no rows come back, I want to move on since the flag is already set to false. I tried it and I keep getting true ever though that code isn't in the database. Can someone help me to get this working properly? Or is there a simpler way to get this task achieved?
#region StateCharges_Status
public static bool StateCharges_Status(DataRow dr) {
bool ok = StateCharges_Exists(dr);
if (ok)
return StateCharges_Update(dr);
else
return StateCharges_Insert(dr);
}
#endregion
#region StateCharges_Exists
private static bool StateCharges_Exists(DataRow dr) {
bool flag = false;
Database pbkDB = DatabaseFactory.CreateDatabase("PbKConnectionString");
DbCommand dbCommand = pbkDB.GetSqlStringCommand(string.Format(#"Select * from tblCtStateCharges where code = '{0}'", dr["Code"].ToString()));
try {
pbkDB.ExecuteNonQuery(dbCommand);
flag = true; // <-- I guess this is where it needs something added.
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
return flag;
}
#endregion
You should change the query to something like:
DbCommand dbCommand = pbkDB.GetSqlStringCommand(string.Format(#"Select count(*) as cnt from tblCtStateCharges where code = '{0}'", dr["Code"].ToString()));
There is no need to select every field when you only care if the record exists.
Then you change the
pbkDB.ExecuteNonQuery(dbCommand);
to something like
int count = (int)pbkDB.ExecuteScalar(dbCommand);
Then change the setting of flag to (you won't need the if anymore)
flag = count > 0;
So the new code would look something like
private static bool StateCharges_Exists(DataRow dr) {
bool flag = false;
Database pbkDB = DatabaseFactory.CreateDatabase("PbKConnectionString");
DbCommand dbCommand = pbkDB.GetSqlStringCommand(string.Format(#"Select count(*) as cnt from tblCtStateCharges where code = '{0}'", dr["Code"].ToString()));
try {
int count = (int)pbkDB.ExecuteScalar(dbCommand);
flag = count > 0;
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
return flag;
}
you should use the ExecuteQuery-method which returns a IEnumerable.
then you can test for result by writing:
var result = pbkDB.ExecuteQuery(dbCommand);
flag = result.Count() > 0;

Get Identity Value from Typed DataSet

I got a typed dataset in my form. Using BindingSource to walk in rows, inserting and updating records.
Everything is fine but I need inserted records identity value for generating a string for my GeneratedCode field in my table.
After getting this value I'll send value to my CodeGen() method and generate string, and update same row's CodeGen field with this value.
I'm using Access database. I know there is that ##Identity thing for Access, but how can I use it? I don't want to use OleDbCommand or something like this.
How can I do that?
string GenCode(int pCariId)
{
string myvalue;
int totalDigit = 7;
myvalue = "CR" + pCariId.ToString();
for (int digit = myvalue.Length; digit <= totalDigit - 1; digit++)
{
myvalue = myvalue.Insert(2, "0");
}
return myvalue;
}
private void dataNavigator_ButtonClick(object sender, NavigatorButtonClickEventArgs e)
{
switch (e.Button.ButtonType)
{
case NavigatorButtonType.EndEdit:
try
{
this.Validate();
if (KaydetFlags == 1)
{
this.bndCariKayit.EndEdit();
datagate_muhasebeDataSet.TB_CARI.Rows[datagate_muhasebeDataSet.Tables["TB_CARI"].Rows.Count - 1]["INS_USR"] = 0;
datagate_muhasebeDataSet.TB_CARI.Rows[datagate_muhasebeDataSet.Tables["TB_CARI"].Rows.Count - 1]["INS_TRH"] = DateTime.Now;
XtraMessageBox.Show("Yeni Cari Kaydı Tamamlandı.");
KaydetFlags = 0;
}
else
{
DataRowView currentRow = (DataRowView)bndCariKayit.Current;
currentRow.Row["UPD_USR"] = "0";
currentRow.Row["UPD_TRH"] = DateTime.Now;
XtraMessageBox.Show("Cari Kaydı Güncellendi.");
this.bndCariKayit.EndEdit();
}
this.tB_CARITableAdapter.Update(datagate_muhasebeDataSet.TB_CARI);
}
catch (System.Exception ex)
{
XtraMessageBox.Show("Kayıt İşlemi Başarısız. Lütfen Tekrar Deneyiniz.");
}
break;
According to documentation you have to use RowUpdated method of your TableAdapter
private static void OnRowUpdated(
object sender, OleDbRowUpdatedEventArgs e)
{
// Conditionally execute this code block on inserts only.
if (e.StatementType == StatementType.Insert)
{
OleDbCommand cmdNewID = new OleDbCommand("SELECT ##IDENTITY",
connection);
// Retrieve the Autonumber and store it in the CategoryID column.
e.Row["CategoryID"] = (int)cmdNewID.ExecuteScalar();
e.Status = UpdateStatus.SkipCurrentRow;
}
}
Another option, which I actually use is to create Select query which simply gets maximum value from you id column:
SelectLastAddedId:
SELECT MAX(id) FROM obmiar
Just set query execute mode to scalar and you can refer to it in your code as
int lastId = TableAdapter.SelectLastAddedId()

Categories

Resources