问题
I have seen a ton of write ups on this and yet cannot get this to work. I have a window in my C# WPF application that, on load, successfully fills a datatable based on a pre-defineds query (altered by user selections from previous window)
The Fill logic is here:
private void FillDataGrid()
{
string ConString = ConfigurationManager.ConnectionStrings["CONN"].ConnectionString;
string CmdString = string.Empty;
using (SqlConnection con = new SqlConnection(ConString))
{
CmdString = $@"select PGCL.Client_Name, PGG.Guarantee_Title, PGG.Guarantee_Desc_Org, PGGM.Target, PGG.Timing_Measurement, PGP.Month, PGP.Year, PGP.Quarter, PGP.Numerator, PGP.Denominator, PGP.Performance_Percent, PGP.Achieved_Flag, PGP.Performance_ID
from PGG
inner join PGC on PGC.Contract_ID = PGG.Contract_ID
inner join PGCL on PGCL.Client_ID = PGC.Contract_ID
inner join PGGM on PGGM.Guarantee_ID = PGG.Guarantee_ID
inner join PGP on PGP.Guarantee_ID = PGG.Guarantee_ID
Where PGP.Month = {this.monthNum.ToString()} and PGP.year = {this.yearNum.ToString()}
and PGC.Active_Flag = 'y'
and PGG.Department_Responsible_ID = {this.deptID.ToString()}
Order by Client_Name, Guarantee_Order asc";
SqlCommand cmd = new SqlCommand(CmdString, con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable("PG");
sda.Fill(dt);
DGPG.ItemsSource = dt.DefaultView;
}
}
This portion works perfectly.
I have 5 columns in the PGP (aliased from above) table that I want to dynamically write values (in a few steps) to based on user input at the close of the window (with a prompt to save). What method would be recommended for doing this?
i.e.: if a user entered the value '5' for for Numerator on row 5 and '7' for denominator on row 10, i want the following to happen:
1) using the PGP.ID, insert into the PGP_History table (for historical logs of changes) 2) UPDATE PGP table values accordingly.
I would greatly appreciate it if someone could get me going in this direction?
Thank you, Wes
EDIT
I think I have made some progress but am stuck on the below, now:
private void FillDataGrid()
{
string ConString = ConfigurationManager.ConnectionStrings["CONN"].ConnectionString;
string CmdString = string.Empty;
using (SqlConnection con = new SqlConnection(ConString))
{
CmdString = $@"select PGCL.Client_Name, PGG.Guarantee_Title, PGG.Guarantee_Desc_Org, PGGM.Target, PGG.Timing_Measurement, PGP.Month, PGP.Year, PGP.Quarter, PGP.Numerator, PGP.Denominator, PGP.Performance_Percent, PGP.Achieved_Flag, PGP.Performance_ID
from PGG
inner join PGC on PGC.Contract_ID = PGG.Contract_ID
inner join PGCL on PGCL.Client_ID = PGC.Contract_ID
inner join PGGM on PGGM.Guarantee_ID = PGG.Guarantee_ID
inner join PGP on PGP.Guarantee_ID = PGG.Guarantee_ID
Where PGP.Month = {this.monthNum.ToString()} and PGP.year = {this.yearNum.ToString()}
and PGC.Active_Flag = 'y'
and PGG.Department_Responsible_ID = {this.deptID.ToString()}
Order by Client_Name, Guarantee_Order asc";
SqlCommand cmd = new SqlCommand(CmdString, con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable("PG");
sda.Fill(dt);
DGPerformanceGuarantees.ItemsSource = dt.DefaultView;
}
}
private void Commit_Updates_Click(object sender, RoutedEventArgs e)
{
string ConString = ConfigurationManager.ConnectionStrings["CONN"].ConnectionString;
//string CmdString = string.Empty;
using (SqlConnection con = new SqlConnection(ConString))
{
//Update Logic
SqlCommand update = new SqlCommand("UPDATE PGP SET PGP.NUMERATOR = @Numerator, DENOMINATOR = @Denominator, PERFORMANCE_PERCENT = @Percent, ACHIEVED_FLAG = '@Achieved' WHERE PERFORMANCE_ID = @Performance_ID", con);
update.Parameters.Add(new SqlParameter("@Numerator", SqlDbType.Int, 5, "NUMERATOR"));
update.Parameters.Add(new SqlParameter("@Denominator", SqlDbType.Int, 5, "DENOMINATOR"));
update.Parameters.Add(new SqlParameter("@Percent", SqlDbType.Decimal, 18, "PERFORMANCE_PERCENT"));
update.Parameters["@Percent"].Precision = 18;
update.Parameters["@Percent"].Scale = 2;
update.Parameters.Add(new SqlParameter("@Achieved", SqlDbType.NVarChar, 1, "ACHIEVED_FLAG"));
update.Parameters.Add(new SqlParameter("@Performance_ID", SqlDbType.Int, 5, "Performance_ID"));
sda.UpdateCommand = update;
sda.Update(dt);
}
FillDataGrid();
}
I added a button to trigger the update to occur. Obviously this does not compile because the SQL Data Adapter (sda) is does not exist in the context of the button handler.
What can I do to resolve this?
回答1:
Well there's a lot of ways to skin this cat.
If you wanted to do an update every time a cell is changed, I would subscribe to the DataGrid
's CellEditEnding
event which will basically inform you whenever a change to the cell has been made and committed by the user. (Check the DataGridCellEditEndingEventArgs
argument to find out which column and cell were actually edited). With that, you can compose a targeted UPDATE
statement and only update the cell that changed.
However, it sounds like you want to do a bulk update when the window closes. In that case, DataTable
will track changes made to the data via the DataGrid
given that you assigned it as the ItemsSource
. When you're ready to commit changes, use DataTable.GetChanges
to get a new DataTable
with just the changed rows since the last time DataDatable.AcceptChanges
was called. Perform your update (use SqlDataAdapter
again this time. See the Update method.) This has the advantage of handling all updates and deletions in a single operation. One disadvantage is that - I believe - every column of the row is going to be updated, so this increases the amount of information that is transmitted to the database server with each update. In any event, then when your update is complete, call DataTable.AcceptChanges
.
That should get you on the right track. Hope this helps.
来源:https://stackoverflow.com/questions/39884384/updating-database-through-edits-to-wpf-datagrid