I am looking in my code if connected user has insert or update permission, stated in the SQL Server. If user has INSERT permission, editing previously saved records in table in datagridview is disabled, and only adding new rows is enabled. And if user has both INSERT or UPDATE permission, user can edit any records in table. My code works great if user has only INSERT permision but if he has both insert and update, i dont know how to cancel that if loop.
Here is my code for CellBeginEdit:
private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
string db2 = Text1;
string user2 = Text2;
string pass2 = Text3;
string selected = this.ComboBox1.GetItemText(this.ComboBox1.SelectedItem);
using (SqlConnection SqlConn = new SqlConnection(#"Data Source=server;Initial Catalog =" + db2 + "; User ID =" + user2 + "; Password =" + pass2 + ""))
{
SqlConn.Open();
SqlCommand SqlCmd2 = new SqlCommand();
SqlCommand SqlCmd3 = new SqlCommand();
SqlCmd2.Connection = SqlConn;
SqlCmd3.Connection = SqlConn;
SqlCmd2.CommandText = "SELECT isnull(has_perms_by_name('" + db2 + ".dbo." + selected + "', 'OBJECT', 'INSERT'), 0)";
SqlCmd3.CommandText = "SELECT isnull(has_perms_by_name('" + db2 + ".dbo." + selected + "', 'OBJECT', 'UPDATE'), 0)";
Int32 number2 = (Int32)SqlCmd2.ExecuteScalar();
Int32 number3 = (Int32)SqlCmd3.ExecuteScalar();
if (number2 == 1)
{
if (!dataGridView1.Rows[e.RowIndex].IsNewRow)
{
if (e.RowIndex < dataGridView1.NewRowIndex)
{
if (AddedRowIndex != e.RowIndex)
{
MessageBox.Show("Not allowed to edit previous records!");
e.Cancel = true;
}
}
}
}
else if ((number2 == 1) && (number3 == 1))
{
//enable editing of all records in table
}
SqlConn.Close();
}
}
The problem appears to be that you're checking for the more simple condition first, and it's going to be true for both Insert and Update, which means the else if condition is never checked and your enable-update code never runs.
Instead, you should check the compound condition first, and if that's false, then check the single condition.
For example:
if (number2 == 1 && number3 == 1)
{
// enable editing of all records
}
else if (number2 == 1)
{
// enable insert only
}
or another option, since they share a condition:
if (number2 == 1)
{
if (number3 == 1)
{
// enable editing of all records
}
else
{
// enable insert only
}
}
Related
I'm having a little bit of a problem with this code. I'm trying to make a code that reads a text from textbox and adds words to database word by word. If word already exist in database, it should increase the number of count that word was added to database, if word doesn't exist, it should add the to database.
Everything is working fine on its own perfectly, but when I input words that exist in database and new words at the same time problem occurs. Code increases count number for existing words as it should, but simply doesn't add new words to the database. And I'm not getting any error.
How to make sure that both functions work at the same for new and old words?
SqlConnection con = new SqlConnection(ConStr);
con.Open();
if (con.State == System.Data.ConnectionState.Open)
{
string raw = rawtxt.Text.ToString();
string[] rawwords = raw.Split(' ');
foreach (var rawword in rawwords)
{
string mon_s = "Select * From Dict";
SqlCommand mon_search = new SqlCommand(mon_s, con);
SqlDataReader srd = mon_search.ExecuteReader();
while (srd.Read())
{
if (srd[1].ToString() == rawword)
{
flag = true;
break;
}
}
srd.Close();
if (flag == false)
{
string raw_lat_c = rawword.Replace("а", "a").Replace("б", "b").Replace("в", "v").Replace("г", "g").Replace("д", "d").Replace("е", "e").Replace("ё", "e").Replace("ж", "j").Replace("з", "z").Replace("и", "i").Replace("й", "i").Replace("к", "k").Replace("л", "l").Replace("м", "m").Replace("н", "n").Replace("о", "o").Replace("ө", "u").Replace("п", "p").Replace("р", "r").Replace("с", "s").Replace("т", "t").Replace("у", "u").Replace("ү", "u").Replace("ф", "f").Replace("х", "h").Replace("ц", "ts").Replace("ч", "ch").Replace("ш", "sh").Replace("щ", "sh").Replace("ъ", "i").Replace("ы", "i").Replace("ь", "i").Replace("э", "e").Replace("ю", "yu").Replace("я", "ya");
int count = 1;
string ins = "Insert into Dict (mongol, latin, count) values(N'" + rawword + "','"+ raw_lat_c +"', '" + count + "')";
SqlCommand command_ins = new SqlCommand(ins, con);
command_ins.ExecuteNonQuery();
}
if (flag == true)
{
string upd_count = "Update Dict Set count=count+1 Where mongol=N'" + rawword + "'";
SqlCommand command_upcnt = new SqlCommand(upd_count, con);
command_upcnt.ExecuteNonQuery();
}
}
}
You have to reset the value of "flag" in every foreach statement. So, before the while, you should do add SqlDataReader srd = mon_search.ExecuteReader(); - like this:
[...]
SqlDataReader srd = mon_search.ExecuteReader();
flag = false;
while (srd.Read())
{
if (srd[1].ToString() == rawword)
{
flag = true;
break;
}
}
[...]
What you are doing now is that once one word in "rawwords" is found in your database, all the remaining words will always be "repeated" because your flag will neve be false.
Change your code like This
if (srd[1].ToString() == rawword)
{
flag = true;
break;
}
else
{
flag = false;
}
I have created a payment in Checks and Payments screen of Acumatica screen and released it. Please refer to the following screenshot.
I've already create the following code to provide it.
protected virtual void APPayment_RowPersisted(PXCache sender, PXRowPersistedEventArgs e)
{
string serverJade, dbJade, userJade, passJade;
serverJade = Properties.Settings.Default.serverJade;
dbJade = Properties.Settings.Default.dbJade;
userJade = Properties.Settings.Default.userJade;
passJade = Properties.Settings.Default.passJade;
APPayment app = (APPayment)e.Row;
if (e.Operation == PXDBOperation.Update && e.TranStatus == PXTranStatus.Completed)
{
if (app.DocType == APPaymentType.Check || app.DocType == APPaymentType.Prepayment)
{
if (app.RefNbr != null)
{
using (SqlConnection con = new SqlConnection("server = " + serverJade + "; database = " + dbJade + "; user = " + userJade + "; password = " + passJade + ""))
{
con.Open();
//---- query to update a field in the table of another database -------//
string query = "Update EVMaster set AcuRefNo = '" + app.RefNbr + "' where VchNo = 'DD02/16-VIII/12206-VCH-01'";
using (SqlCommand com = new SqlCommand(query, con))
{
SqlDataReader sdr = com.ExecuteReader();
sdr.Close();
}
con.Close();
}
}
}
}
}
I already tried to debug this code, but didn't work. And then I try to use this follwing code.
protected virtual void APPayment_RowPersisted(PXCache sender, PXRowPersistedEventArgs e)
{
string serverJade, dbJade, userJade, passJade;
serverJade = Properties.Settings.Default.serverJade;
dbJade = Properties.Settings.Default.dbJade;
userJade = Properties.Settings.Default.userJade;
passJade = Properties.Settings.Default.passJade;
APPayment app = (APPayment)e.Row;
if (app.DocType == APPaymentType.Check || app.DocType == APPaymentType.Prepayment)
{
if (app.RefNbr != null)
{
using (SqlConnection con = new SqlConnection("server = " + serverJade + "; database = " + dbJade + "; user = " + userJade + "; password = " + passJade + ""))
{
con.Open();
//---- query to update a field in the table of another database -------//
string query = "Update EVMaster set AcuRefNo = '" + app.RefNbr + "' where VchNo = 'DD02/16-VIII/12206-VCH-01'";
using (SqlCommand com = new SqlCommand(query, con))
{
SqlDataReader sdr = com.ExecuteReader();
sdr.Close();
}
con.Close();
}
}
}
}
The codes above is worked, I just remove the if condition (if (e.Operation == PXDBOperation.Update && e.TranStatus == PXTranStatus.Completed)
{}).
But it's not my goal, I have to filter document only for Doc Status = 'printed' from the document, and this process will be executed when 'Release' button was clicked.
And also any idea how to get all records in APAdjust of the current document ? because I need to comparing adjgrefnbr in apadjust with refnbr in APInvoice based on adjgrefnbr (apadjust) = refnbr (apinvoice). So I can get also all records of APinvoice based on refnbr (APinvoice) = ajgrefnbr (current apadjust). This condition is used to make 'where' condition of query not have to be hardcoded, I will used variable to provide it.
any suggestions to sove this problem ?
Below is an example showing how to extend Release process for checks and subscribe to RowPersisted handler for the APRegister DAC to save released document RefNbr to another database:
public class APPaymentEntryExt : PXGraphExtension<APPaymentEntry>
{
public PXAction<APPayment> release;
[PXUIField(DisplayName = "Release", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXProcessButton]
public IEnumerable Release(PXAdapter adapter)
{
PXGraph.InstanceCreated.AddHandler<APReleaseProcess>((graph) =>
{
graph.RowPersisted.AddHandler<APRegister>(APReleaseCheckProcess.APPaymentRowPersisted);
});
return Base.release.Press(adapter);
}
}
public class APReleaseChecksExt : PXGraphExtension<APReleaseChecks>
{
protected virtual void ReleaseChecksFilter_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var row = e.Row as ReleaseChecksFilter;
if (row == null) return;
Base.APPaymentList.SetProcessDelegate(list =>
{
PXGraph.InstanceCreated.AddHandler<APReleaseProcess>((graph) =>
{
graph.RowPersisted.AddHandler<APRegister>(APReleaseCheckProcess.APPaymentRowPersisted);
});
APReleaseChecks.ReleasePayments(list, row.Action);
});
}
}
By executing quite simple BQL query you can access APAdjust records associated with released check within handler for the RowPersisted event:
public static class APReleaseCheckProcess
{
public static void APPaymentRowPersisted(PXCache sender, PXRowPersistedEventArgs e)
{
if (e.TranStatus == PXTranStatus.Completed && e.Operation == PXDBOperation.Update)
{
var doc = e.Row as APPayment;
if (doc != null && doc.Released == true)
{
// save RefNbr to another database
foreach (APAdjust oldadj in PXSelect<APAdjust,
Where<
APAdjust.adjgDocType, Equal<Required<APPayment.docType>>,
And<APAdjust.adjgRefNbr, Equal<Required<APPayment.refNbr>>,
And<APAdjust.adjNbr, Less<Required<APPayment.lineCntr>>>>>>
.Select(sender.Graph, doc.DocType, doc.RefNbr, doc.LineCntr))
{
}
}
}
}
}
I am building a simple Point of Sale program and working on a "search invoice" button that allows up to 3 search criteria (InvoiceID , ClientName, and ClientID). These are the names of 3 of the columns in the table named "Invoicing".
InvoiceID is the key column of type Int32, ClientName is of type String, ClientID is of type Int32. ClientName and ClientID searches work perfect.
MY PROBLEM: If I include InvoiceID in the select query, I get the following error. And I have spent a few days trying to figure it out.
ERROR: Database Error: Datatype mismatch in criteria expression.
Can you more experienced programmers help me out? thank you!
String connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data" + #" Source=TESTDB.accdb";
String tableName = "Invoicing";
String query = String.Format("select * from [{0}] where", tableName);
//ADD IN SEARCH CRITERIA
int filled = 0;
if (invoiceBox.Text != "") { query += " InvoiceID='" + invoiceBox.Text+"'"; filled += 1; }
/*if (DateCheckBox.Checked == true)
{
if (filled>=1) { query += " and DateNTime='" + monthCalendar1.SelectionStart.ToString() + "'"; filled += 1; }
else { query += " DateNTime='" + monthCalendar1.SelectionStart.ToString()+ "'"; filled += 1; }
}
* */
if (ClientNameBox.Text != "") //Doesnot work
{
if (filled >= 1) { query += " and Client='" + ClientNameBox.Text + "'"; filled += 1; }
else { query += " Client='" + ClientNameBox.Text + "'"; filled += 1; }
}
if (ClientIDBox.Text != "") //THIS search criteria works!!!!
{
if (filled >= 1) { query += " and ClientID='" + ClientIDBox.Text + "'"; filled += 1; }
else { query += " ClientID='" + ClientIDBox.Text + "'"; filled += 1; }
}
//CHECK IF SEARCH CRITERIA ARE PRESENT
if (filled < 1) { MessageBox.Show("At least One Search criteria above is required"); return; }
DataSet dsInvoicing = new DataSet();
OleDbConnection conn = new OleDbConnection(connectionString);
try
{
//Open Database Connection
conn.Open();
OleDbDataAdapter daInvoicing = new OleDbDataAdapter(query, conn);
//Fill the DataSet
daInvoicing.Fill(dsInvoicing, tableName);
//MessageBox.Show("dsInventory has "+dsInventory.Tables[0].Rows.Count+" search results");
conn.Close();
this.dataGridView1.DataSource = dsInvoicing.Tables[0];
}
catch (OleDbException exp){ MessageBox.Show("Database Error: " + exp.Message.ToString());}
Need more information? I will post up more if I haven't provided enough.
DATABASE INFORMATION or other.
Thank you very much to all programmers.
Looks like the data type of InvoiceID in your database is some numeric kind. While in query you are treating it as string. Try not to wrap InvoiceID value in single quotes.
I have a form which displays selected datagridviewrow data in textboxes. I would like to edit and update the data from this form and update and save into the datatable when the user clicks update.
When I click update I get an error message:
There was an error parsing the query. [ Token line number = 1,Token line offset = 25,Token in error = ( ]
private void editBTN_Click(object sender, EventArgs e)
{
bool notEditable = true;
if (editBTN.Text == "Update")
{
UpdateDataBase();
editBTN.Text = "Edit";
deleteBTN.Visible = true;
notEditable = true;
}
else
{
deleteBTN.Visible = false;
editBTN.Text = "Update";
deleteBTN.Visible = false;
notEditable = false;
}
firstTxt.ReadOnly = notEditable;
surenameTxt.ReadOnly = notEditable;
address1Txt.ReadOnly = notEditable;
address2Txt.ReadOnly = notEditable;
countyTxt.ReadOnly = notEditable;
contactTxt.ReadOnly = notEditable;
emailTxt.ReadOnly = notEditable;
postTxt.ReadOnly = notEditable;
}
private void UpdateDataBase()
{
if (MessageBox.Show("Customer information will be updated. This change cannot be undone. Are you sure you want to continue? ", "Confirm Edit", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
string constring = #"Data Source=|DataDirectory|\LWADataBase.sdf";
string Query = "update customersTBL set ([First_Name] = '" + this.firstTxt.Text + "',surename= '" + this.surenameTxt.Text + "',[Address Line 1] = '" + this.address1Txt.Text + "',[Address Line 2] = '" + this.address2Txt.Text + "',County = '" + this.countyTxt.Text + "',[Post Code] = '" + this.postTxt.Text + "' , Email = '" + this.emailTxt.Text + "';,[Contact Number] = '" + this.contactTxt.Text + "');";
SqlCeConnection conDataBase = new SqlCeConnection(constring);
SqlCeCommand cmdDataBase = new SqlCeCommand(Query, conDataBase);
SqlCeDataReader myReader;
try
{
conDataBase.Open();
myReader = cmdDataBase.ExecuteReader();
MessageBox.Show("Customer information has been updated", "Update Sucessful");
while (myReader.Read())
{
}
MessageBox.Show("Please exit the Customers window and re-open to update the table");
this.Close();
//displays a system error message if a problem is found
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
There are some problems in your code.
One is trivial and could be easily fixed (remove the semicolon before the [Contact Number], but there are other hidden problems that potentially are more serious.
First: Remember to always close and dispose the disposable objects
(connection and command in this case). The using statement ensure
that the object enclosed by the using block will be correctly closed
and disposed also in case of exceptions
Second: Use a parameterized query. This avoids Sql Injections and
parsing problems. If one or more of your input data contains a single
quote, the string concatenation used to build the sql command text
will resul in an invalid command
Third: An update command acts on all the records present in the table
if you don't add a WHERE condition. Usually the WHERE condition is
added to identify the only record that need to be updated and it is
the value of a field with UNIQUE index or the PRIMARY KEY of your
table. Of course you could update more than one record with a less
restrictive WHERE clause but this doesn't seem to be the case
Fourth: Use the ExecuteNonQuery instead of ExecuteReader for commands
that update/insert the database (well it works equally but why use a
method that should be reserved for other uses?)
private void UpdateDataBase(int customerID)
{
string constring = #"Data Source=|DataDirectory|\LWADataBase.sdf";
string Query = #"update customersTBL set [First_Name] = #fname,
surename = #sur, [Address Line 1] = #addr1,
[Address Line 2] = #addr2, County = #county,
[Post Code] = #pcode, Email = #mail, [Contact Number] = #ctNo
WHERE customerID = #id";
using(SqlCeConnection conDataBase = new SqlCeConnection(constring))
using(SqlCeCommand cmdDataBase = new SqlCeCommand(Query, conDataBase))
{
try
{
conDataBase.Open();
cndDataBase.Parameters.AddWithValue("#fname", this.firstTxt.Text);
cndDataBase.Parameters.AddWithValue("#sur", this.surenameTxt.Text );
cndDataBase.Parameters.AddWithValue("#addr1", this.address1Txt.Text );
cndDataBase.Parameters.AddWithValue("#addr2", this.address2Txt.Text );
cndDataBase.Parameters.AddWithValue("#county", this.countyTxt.Text );
cndDataBase.Parameters.AddWithValue("#pcode", this.postTxt.Text );
cndDataBase.Parameters.AddWithValue("#mail", this.emailTxt.Text );
cndDataBase.Parameters.AddWithValue("#ctNo", this.contactTxt.Text );
cndDataBase.Parameters.AddWithValue("#id", customerID );
int rowsUpdated = cmdDataBase.ExecuteNonQuery();
if(rowsUpdate == 0)
MessageBox.Show("No customer found to update");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
As you can see, with a parameterized query is more difficult to write a bad sql text with hidden problems and the quoting job is passed to the database code that knows better how to format the parameter values.
The only problem that you need to solve is how to retrieve the value for the customerID or some other value that you could use in the WHERE clause to uniquely identify the record of your customer
In this point you call the UpdateDatabase method that now required a UserID variable containing the key to identify your user on the table
private void editBTN_Click(object sender, EventArgs e)
{
bool notEditable = true;
if (editBTN.Text == "Update")
{
// Here you need to identify uniquely your modified user
// Usually when you load the data to edit you have this info extracted from your
// database table and you have saved it somewhere
// (of course the user should not edit in any way this value
int UserID = ... ???? (from an hidden textbox? from a global variable, it is up to you
UpdateDataBase( UserID );
I think your confusing the Update structure with an Insert.
For your update it looks like this:
update customersTBL set ([First_Name] = 'data', surename= '',[Address Line 1] = '',[Address Line 2] = '',County = '',[Post Code] = '' , Email = '';,[Contact Number] = '');
You need a where clause.
Update/Set does not put the changes in ()
After email you have a ';'
what is wrong with this code what i am actually to achieve is
insert rows to database clear the textbox value and enter another record..
the problem is at first loop data will be added successfully...but on the next iteration loops it will add empty strings to the rows of database but what i want is accept input from textbox and continue iterating...please try to read the code and help me ...it is been 2 weeks since am trying so solve this ..
again what i want to do
-user enter number of group members
- the group members have column like ,first name,last name gender,city.etc
FOR all the group members (eg:6 group membrs) add 6 rows of of different column will be added
but my code does is add the first rows and the rest 5 row's will be empty data
Sorry for my bad english..somebody please try to think what i am thinking
{{
private void btnAddloan_Click(object sender, RoutedEventArgs e)
if (txtname.Text != "" && txtlname.Text != "")
{
int c=0;
int input=int.Parse(txttotalnumberofgroupmembers.Text);
do
{
string connstr = "Data Source=GER-PC\\PLEASEGOD;Initial Catalog=ACSI;Integrated Security=True";
SqlConnection con = new SqlConnection(connstr);
con.Open();
SqlCommand cmd = new SqlCommand("insert into Customer(FirstName,LastName) values(#n,#p)", con);
cmd.Parameters.AddWithValue("#p", txtname.Text);
cmd.Parameters.AddWithValue("#n", txtlname.Text);
cmd.ExecuteNonQuery();
con.Close();
lblnotify.Content = c + 1 + "" + "members added";
//clear textbox values and wait for another input
txtname.Text = "";
txtlname.Text = "";
if (txtname.Text != "" && txtlname.Text != "")
{
continue;
}
else
{
MessageBoxResult result =MessageBox.Show("procces","Continue Adding Memebers",MessageBoxButton.YesNoCancel,MessageBoxImage.Warning);
//txtname.Text = s;
//txtlname.Text= s1;
//MessageBox.Show();
switch (result)
{
case MessageBoxResult.Yes:
if (txtname.Text != "")
{
}
else
{
}
break;
case MessageBoxResult.No:
break;
case MessageBoxResult.Cancel:
break;
}
}
c++;
} while (c < input);
}
else
{
MessageBox.Show("plese fill first name and last name");
}
}
You're clearing the txtname.Text and txtlname.Text value after you do the insert. In the next iteration you're recreating the Parameters, but this time your text values are EMPTY.
txtname.Text = "";
txtlname.Text = "";
Instead of recreating your command object, why not just execute the command object N times. Like:
SqlCommand cmd = new SqlCommand("insert into Customer(FirstName,LastName) values(#n,#p)", con);
cmd.Parameters.AddWithValue("#p", txtname.Text);
cmd.Parameters.AddWithValue("#n", txtlname.Text);
for(int i = 0; i < input; i++)
{
cmd.ExecuteNonQuery();
}