I am making a query involving 2 tables in C#. The query works fine when I input information into all the combo boxes. But when I try to make query with some empty combo boxes, it returns nothing.
I get that it is cos the string ends up having "" in the query which makes it invalid. Is there anyway I could restructure my query to make it possible to make queries with missing entries or even a missing secondary table? Thanks for advice.
The following works when I fill up all fields and make the query:
If I fill up only paritial fields as follows, it won't work:
My query String:
string query = #"SELECT Agents." + comboq1.Text + ", Agents." + comboq2.Text + ", Agents." + comboq3.Text + ", Agents." + comboq4.Text + ", "
+ secondaryTable.Text + "." + stCombo1.Text + ", " + secondaryTable.Text + "." + stCombo2.Text
+ " FROM Agents INNER JOIN " + secondaryTable.Text + " ON Agents.Dept_ID" + "="
+ secondaryTable.Text + ".Dept_ID";
string agentsValue = string.empty;
if (!comboq1.Text.equals(string.empty))
{ agentsValue = "Agents."+comboq1.text; }
if (!agentsValue.equals(string.empty))
{ agentsValue +=","; }
if (!comboq2.Text.equals(string.empty))
{
if (agentsValue.equals(string.empty))
{ agentsValue = "Agents."+comboq2.text; }
else
{ agentsValue += "Agents."+comboq2.text; }
}
please follow the above code for rest of the combo boxes and while adding the value of the second combo box add a comma in between the values. After building the string in this format you can then append it to your query and now when you execute the query you should not find any kind of errors.
Hope this helps
I would suggest that you use a separate string by checking that if any combo box does not provide any value then omit that combo box value from the string and then append the final string to you query which will not cause any problem.
Related
I have the following code:
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
string age = dataGridView1.Rows[e.RowIndex].Cells["dataGridViewTextBoxColumn43"].Value.ToString();
dataGridView1.Rows[e.RowIndex].Cells["dataGridViewTextBoxColumn43"].Value = (age == "1") ? "Муж" : "Жен";
}
When I run program it gives fatal message:
In database field gender is as integer type. This value should be added to column name: dataGridViewTextBoxColumn43.
Query to database:
public DataTable select(SQLiteDatabase db)
{
return db.GetDataTable("SELECT " +
"Pacients.id, " +
"unique_code," +
"status_pass, " +
"payment, " +
"profession," +
"office_address, " +
"factory_name, " +
"factory_edrpou, " +
"factory_departament," +
"name, " +
"secondname, " +
"lastname, " +
"datebirth, " +
"taxcode, " +
"gender, " +
"Pacients.created_at, " +
"file, " +
"PacientsOrder.kind_work, " +
"PacientsOrder.status " +
"FROM Pacients LEFT JOIN PacientsOrder ON PacientsOrder.pacient_id = Pacients.id LEFT JOIN Transactions ON Transactions.pacient_id = Pacients.id ORDER BY Pacients.id DESC");
}
If the column ValueType is numeric, you can change the number format in the designer to Муж;;Жен
dataGridView1.Columns["dataGridViewTextBoxColumn43"].DefaultCellStyle.Format = "Муж;;Жен";
If I understand you correctly, you are trying to add a text value to a column, based on an integer value which is currently in the same column (ie you are switching column value types)?
Please do not do it this way, as it will not work for several reasons. Apart from your error, the most important being that this event is fired when you set the DataSource of your DataGridView for every row created, but the e.RowIndex is not always the RowIndex of the new row. For full details read here.
Normally you would only use RowsAdded when the user has inserted a new row from the interface.
What you should do instead, is to provide this conversion in your SELECT statement that reads the data from the database. That way you do not need to convert the data when it hits the DataGridView. So your SELECT needs to be something like:
SELECT .... CASE WHEN gender = 1 THEN 'МУЖ' ELSE 'ЖЕН' END AS gender ...
Edit
Try changing your SELECT statement so it reads as follows:
public DataTable select(SQLiteDatabase db) {
return db.GetDataTable("SELECT " +
"Pacients.id, " +
"unique_code," +
"status_pass, " +
"payment, " +
"profession," +
"office_address, " +
"factory_name, " +
"factory_edrpou, " +
"factory_departament," +
"name, " +
"secondname, " +
"lastname, " +
"datebirth, " +
"taxcode, " +
"CASE WHEN gender = 1 THEN 'МУЖ' ELSE 'ЖЕН' END AS gender, " +
"Pacients.created_at, " +
"file, " +
"PacientsOrder.kind_work, " +
"PacientsOrder.status " +
"FROM Pacients LEFT JOIN PacientsOrder ON PacientsOrder.pacient_id = Pacients.id LEFT JOIN Transactions ON Transactions.pacient_id = Pacients.id ORDER BY Pacients.id DESC");
}
Now you can get rid of the add rows event completely, as the database has done the work for you, before it hits the datagridview.
The problem was the folowing, it is obvios, but not clear at once:
The gender field is stored in database as integer type.
So, when I bind DataGridView with existing database table It allocates memory for building table with defination all properties of table, including cell types.
Therefore, when it happends at the first time, the datagridview expects to get integer data type as value, but I modify the value cell to string value and try to overwrite value.
It involkes an fatal error.
Solution was to change all data types that have got integer to string type.
Thanks for answers, it will be accepted!
I have this line of code:
sql += " AND lc.name IN ('" + String.Join(",", id.type.ToArray()) + "')";
There are two items in id.type and this code generates this:
AND lc.name IN ('towns back to back,towns 3 storey')
Which will not work because it should be like this:
AND lc.name IN ('towns back to back' , 'towns 3 storey')
How can I fix this?
This is not a desirable approach, because it's open to SQL injection. But there are a few things:
You have to accommodate for strings that contain single quotes.
It won't work if you just concatenate. You have to wrap EACH item in single quotes.
Try:
sql += " AND lc.name IN (" + String.Join(",", id.type.ToArray().Select(i=>String.Format(i.Replace("'","''"),"'{0}'")) + ")";
Use parameter to pass input string like
sql += " AND lc.name IN (#inputname)";
sqlcommand.parameters.AddWithValue("#inputname", String.Join("','", id.type.ToArray()))
I'm looking a way to convert this query:
Select *
From Tasks
Where Addresses_Street1+' '+Addresses_Street2+' '+Addresses_City +' '+Addresses_ZipCode Like '%'+replace(ltrim(rtrim('Leon Deladriere 15')),' ','%')
to a Linq C# expression.
I know that Contains() and Trim() can be use for the method but how to handle the replace ' ' by '%' ?
This expression is used to provide to user one single input with an address and look into multiples columns to find a matching one.
I use Linqpad but I doesn't see equivalent in Linq
You can try.
(from r in Tasks where SqlMethods.Like(
r.Addresses_Street1 + " " +
r.Addresses_Street2 + " " +
r.Addresses_City + " " +
r.Addresses_ZipCode,
"%Leon Deladriere 15".Trim().Replace(" " , "%"))
select r)
Note, LinqSql is smart enough to know that it can do the Trim and Replace locally rather than asking Sql to do it.
However if you use a field rather than a constant, eg
(from r in Task where SqlMethods.Like( ... ,
r.Addresses_Street1 + " " +
r.Addresses_Street2 + " " +
r.Addresses_City + " " +
r.Addresses_ZipCode,
r.AnotherField.Trim().Replace(" " , "%"))
select r)
then this will ask sql to do the trim and replace.
Try this:
var user = "Leon Deladriere 15".Trim();
Tasks.Where(t => (t.Addresses_Street1 + t.Addresses_Street2 + t.Addresses_City + t.Addresses_ZipCode).Contains(user));
I am trying to input data from four text boxes into a Firebird database. Every time I click the button that executes the following code, I get an "SQL Error = -804 Count of read-write columns does not equal count of values."
I'm not sure what this error means. The code I have is:
private void button1_Click(object sender, EventArgs e)
{
string ConnectionString = "User ID=sysdba;Password=masterkey;" +
"Database=localhost:G:\\nael.FDB; " +
"DataSource=localhost;Charset=NONE;";
FbConnection addDetailsConnection = new FbConnection(ConnectionString);
addDetailsConnection.Open();
FbTransaction addDetailsTransaction =
addDetailsConnection.BeginTransaction();
string SQLCommandText = " INSERT into Invoice_Name Values" +
"('" + textBox1.Text + "',' "
+ textBox2.Text + "',' "
+ int.Parse(textBox3.Text) + "',' "
+ textBox4.Text + "',' "
+ "')";
FbCommand addDetailsCommand = new FbCommand(SQLCommandText,
addDetailsConnection, addDetailsTransaction);
addDetailsCommand.ExecuteNonQuery();
addDetailsTransaction.Commit();
MessageBox.Show(" Details Added");
}
I bet one of your TextBox.Text values has a comma in it... Otherwise: Did you check to see if you are specifying the right amount of columns?
Basically, the SQL engine is complaining that you gave it a list of parameters and it is trying to fill those into the table Invoice_Name, except, it has too many values for the count of columns in that table. Try printing SQLCommandText to the output window (Debug.WriteLine(SQLCommandText)) and see if that is what you expect it to be...
You should also not be doing it this way... check this post here: Inserting into DB with parameters safe from SQL injection?
there are other question (at least 2 I've seen them) similar to this but I'm not able to solve this using them.
Now the problem: I've 3 table from which I need to select 4 columns only. I'm using InnerJoin and it is working perfectly. Problem starts when I add a Where to this Select. I've a column named "Name" in two tables. If I add simply the
.Where("Name").Like("A%")
It says "... ambiguous column name.."
If I use fully qualified column name (with table prefixed to column name) it says must declare parameter #TABLE_NAME
SqlQuery sq = new Select(Tables.TableOne + "." + TableOne.Columns.MemberId +
" AS MemberId",
Tables.TableTwo + "." + TableTwo.Columns.Name + " AS MemberName",
Tables.TableOne + "." + TableOne.Columns.ExpiryOn + " AS MembershipExpiresOn",
Tables.TableFour + "." + TableFour.Columns.Name + " AS Country")
.From(DAL.Tables.TableOne)
.InnerJoin(Tables.TableTwo)
.InnerJoin(Tables.TableThree)
.InnerJoin(Tables.TableFour, TableFour.Columns.CountryCode,
Tables.TableThree, TableThree.Columns.CountryOfBirth).
sq.Where(Tables.TableTwo + "." + TableTwo.Columns.Name).Like("A%");
I've tried to pass hard-coded string also but nothing works!
If you pass in the column object to the Where statement SubSonic will use it's fully qualified name instead of building a string. You can find the column on the object as a static property, so in this case if you have an object called "TableOne" you can use "TableOne.NameColumn" and pass that into the Where():
...
sq.Where(TableTwo.NameColumn).Like("A%");
Does the following query work, I'm assuming you're using 2.2:
SqlQuery sq = new Select(TableOne.Columns.MemberId + " AS MemberId",
TableTwo.Columns.Name + " AS MemberName",
TableOne.Columns.ExpiryOn + " AS MembershipExpiresOn",
TableFour.Columns.Name + " AS Country")
.From(TableOne.Schema)
.InnerJoin(TableTwo.Schema)
.InnerJoin(TableThree.Schema)
.InnerJoin(TableFour.Schema)
.Where(TableTwo.Columns.Name).Like("A%");
I haven't used it ever,
but have your tried to change your last line to:
sq.WhereExpression(Tables.TableTwo + "." + TableTwo.Columns.Name + " LIKE 'A%');