I am in the process of converting an in-house web app to a winform app for disconnected reasons and I hit the following snag.
In the Function SaveMe() on the webapp there is the following code on the Person.ascx.vb page -->
//get dataset from session
Dim dsPerson As Data.DataSet = CType(Session.Item("Person" & Me.UniqueID), DataSet)
//if no rows in dataset, add
If dsPerson.Tables(0).Rows.Count = 0 Then
Dim rowPerson As Data.DataRow = dsPerson.Tables(0).NewRow
dsPerson.Tables(0).Rows.Add(FillPersonRow(rowPerson))
Else
//otherwise update
....more code here
The part I am stuck on is how to logically create a dataset on a WinForm app?
Should I just scrape all the fields and throw them into a DataSet? How(this is what I will research/try while waiting for advice from SO)?
EDIT
The Session is getting created/populated in the LoadMe() Sub, like so -->
//load person
Dim dsTemp As Data.DataSet = BLL.Person.GetPerson(PersonID)
//save to session state
Session.Add("Person" & Me.UniqueID, dsTemp)
EDIT
What I am trying to do is create a Form level variable --> private DataSet _personInfo; to hold the DataSet then in my FormPaint(int personID) I call the following:
_personInfo = ConnectBLL.BLL.Person.GetPerson(personID);
I then use that to populate the various fields on the Form.
Next, on btnUpdate_Click() I try the following but to no avail:
void btnUpdate_Click(object sender, EventArgs e)
{
var areChanges = _personInfo.HasChanges();
if (areChanges)
{
var whatChanged = _personInfo.GetChanges();
var confirmChanges =
MessageBox.Show(
"Are you sure you want to make these changes: " +
whatChanged.Tables[0].Rows[0].ItemArray.ToString(), "Confirm Member Info Changes",
MessageBoxButtons.YesNo, MessageBoxIcon.Hand);
if (confirmChanges == DialogResult.Yes)
{
_personInfo.AcceptChanges();
ConnectBLL.BLL.Person.Update(_personInfo);
}
}
FormPaint(HUD.PersonId);
}
I am unclear what I am doing wrong? Am I missing a step?
Thank you
First,
If you want a good explanation of the issue that Jacob raised read the following article...
http://www.knowdotnet.com/articles/datasetmerge.html
And I agree with the others that you seem to be making it harder than it needs to be.
You are not clear what the ConnectBLL class is...is that a custom bizness object or a strongly typed dataset.
To do databinding which will automatically save would be a very long post so in lieu of that here are a couple of links.
http://www.codeguru.com/columns/vb/article.php/c10815
http://support.microsoft.com/kb/313482
http://msdn.microsoft.com/en-us/library/aa984336(VS.71).aspx
Those were the first links I found on google using (step by step instruction on winforms databinding with a strongly typed dataset) as the search string. You might find a better one. The codeguru link looked pretty good. The other to are more thorough at the expense of being more technical.
Best of all...if you can spring for Chris Sells book in winforms development, the chapters on data binding are excellent (along with all of the other chapters.)
http://www.amazon.com/Windows-Forms-Programming-Microsoft-Development/dp/0321267966/ref=sr_1_1?ie=UTF8&qid=1249525202&sr=8-1
Hope this helps.
In that snippet, the DataSet comes from session. When is it set ?
You certainly can use a DataSet in a WinForms application. Is it the databinding, you are having trouble with ?
Your problem is likely here:
if (confirmChanges == DialogResult.Yes)
{
_personInfo.AcceptChanges();
ConnectBLL.BLL.Person.Update(_personInfo);
}
AcceptChanges sets the RowState to Unchanged on all rows that were ready to be updated. Frankly, it'd probably be better to use whatChanged as that'll keep your adapter from having to re-check for changed rows.
if (confirmChanges == DialogResult.Yes)
{
ConnectBLL.BLL.Person.Update(whatChanged);
_personInfo.AcceptChanges();
}
Related
I have a program I created in Visual studio. The program is basically a place for everyone to store passwords for company and external accounts. I want to further this application by automatically creating the company accounts when I create a new user. I approached this by using the binding source. I can get the row into the database but it doesn't use the sql supplied auto increment. I will post the code but I am trying to figure out if I went about this the wrong way. I am not 100% familiar with how the connector and classes that visual studio create when you connect the solution to the database. I am not looking for code to help me do this I am looking for explanations and guidance. If responding with code please help me understand by explaining the code.
DataSet.AccountsRow newdomainuserrow = DBDataSet.Accounts.NewAccountsRow();
newdomainuserrow.USer = userIDTextBox.Text.ToString();
newdomainuserrow.UserName = userIDTextBox.Text.ToString();
System.DateTime moment = new DateTime();
newdomainuserrow.Password = moment.Year;
newdomainuserrow.AccountName = "Domain";
drawingNumDBDataSet.Accounts.Rows.Add(newdomainuserrow);
MessageBox.Show("User Saved");
this.Validate();
this.usersBindingSource.EndEdit();
this.accountBindingSource.Endedit();
this.tableAdapterManager.UpdateAll(this.DataSet);
All help is greatly appreciated.
Matt
I found a solution. The id field is not longer an identity autoincrement field. To increment the id field one by one programmatically like I need to I wrote a simply while statement to get all numbers that were not used. This works if there is a deleted row it will insert one where there is one missing. here is the code I used.
Boolean gotnum;
gotnum = false;
int idnum = 1;
while (gotnum != true)
{
DrawingNumDBDataSet.AccountsRow actrw = drawingNumDBDataSet.Accounts.FindById(idnum);
idnum++;
if (actrw==null)
{
gotnum = true;
idnum--;
}
}
I then set the Id field = to idnum. This is probably not the best practice but it is the best I could come up with.
I'm using VS2k10 to write a C# program that requires a username and a password to run. I have a database saved in an external file with the usernames and passwords. When I click register in the login form, another form opens that allows you to save your credentials to the login database.
The problem is probably in the register form, not the login one. When I successfully register a user account, the login form doesn't seem to recognize that username. It doesn't save to the file either. Checked SE on how to commit changes to the dataset, but nothing works so far.
My current code is:
DataRow foundRow = ds.Tables["userstable"].Rows.Find(username.Text);
if (foundRow != null)
{ MessageBox.Show("Username already exists!"); }
else
{
DataRow newrow = ds.Tables["userstable"].NewRow();
newrow["ID"] = username.Text;
newrow["hash"] = CalculateMD5Hash(password.Text + username.Text + "hambába");
ds.Tables["userstable"].Rows.Add(newrow);
username.Text = "";
password.Text = "";
repeatpass.Text = "";
ds.AcceptChanges();
MessageBox.Show("Registration complete!");
}
"ds" is the dataset used.
The table has two columns - "ID" and "hash", which contain the username and the hash counted from the password. What's the issue, did I miss something?
ds.AcceptChanges(); do not update, but sign to ignore the changes. for update you need use a DataAdapter with commands for update and use the Update() method:
DataAdapter.Update(ds);
Where is the DataAdapter you are using to fill the DataSet? You need to do something like this.
try
{
SqlDataAdapter1.Update(Dataset1.Tables["Table1"]);
}
catch (Exception e)
{
// Error during Update, add code to locate error, reconcile
// and try to update again.
}
See this link for more information https://msdn.microsoft.com/en-us/library/xzb1zw3x.aspx
I would also recommend that you separate out the code that writes to the database from the code that affects the UI. Look here for what an MVC (Model View Controller) pattern is. http://blog.codinghorror.com/understanding-model-view-controller/ and look here for a beginner tutorial on ASP.NET MVC http://www.w3schools.com/aspnet/mvc_app.asp
I don't know your setup but ds.AcceptChanges(); don't write changes to underlying database. If you've setup it to work like that you have to show your code but AcceptChanges alone doesn't enough. MSDN:When you call AcceptChanges on the DataSet, any DataRow objects still in edit-mode end their edits successfully. The RowState property of each DataRow also changes; Added and Modified rows become Unchanged, and Deleted rows are removed.
I am updating rows of featureclasses via a plugin using C# and ArcObjects. For some reason the featureclasses then are not refreshing properly when the slider is moved, they do display properly if I manually refresh the map, however. I want to test if forcing a full refresh of the display on timeslider updates will work around the issue. In order to do that I want to listen for timeslider update events in my code.
I have seen another bug related to ArcSDE Direct Connection tables not displaying properly, but this is not my issue as I am not using an ArcSDE Direct Connection.
I have also recomputed attribute indexes (on time field) and spatial indexes but no dice.
So, hoping that refreshing on timeslider updates might help.
My C# plugin is running in ArcMap 10.1 SP1. Background enterprise geoDB is on SQLServer.
Thanks!
After a day of searching I posted my question, then found my solution within an hour.
ITimeDisplayEvents_DisplayTimeChangedEventHandler DTC_EH;
private void enableTimeDisplayEventHandler(bool enable = true)
{
IMxDocument pMxDoc = ArcMap.Document;
IMap pMap = pMxDoc.FocusMap;
IActiveView pActiveView = pMap as IActiveView;
IScreenDisplay pScreenDisplay = pActiveView.ScreenDisplay;
ITimeDisplay pTimeDisplay = pScreenDisplay as ITimeDisplay;
DTC_EH = new ITimeDisplayEvents_DisplayTimeChangedEventHandler(this.OnDisplayTimeChangedEventHandler);
((ITimeDisplayEvents_Event)pTimeDisplay).DisplayTimeChanged += DTC_EH;
}
private void OnDisplayTimeChangedEventHandler(IDisplay d, object oldvalue, object newvalue)
{
IMxDocument pMxDoc = ArcMap.Document;
IMap pMap = pMxDoc.FocusMap;
IActiveView pActiveView = pMap as IActiveView;
pActiveView.Refresh();
}
Hopefully somebody else finds that useful.
My company has gone from 2 people to 4 people recently and I have had to add user tracking and the like. With that said I am now trying to tackle a way for people to see when others are in a record. I have a datagridview that is a case selector and when someone double clicks it opens the main form for that case. I need to be able to across users be able to show or at the very list stop them from going into that record. I have absolutely not idea how to do this in winforms and am hoping someone could help me modify what I already have to do this.
The code being used to open the form is below:
private void caseSelectorDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
System.Data.DataRowView SelectedRowView;
//newCityCollectionDataSet.PropertyInformationRow SelectedRow;
newCityCollectionDataSet.CaseSelectorRow SelectedRow;
SelectedRowView = (System.Data.DataRowView)caseSelectorBindingSource.Current;
SelectedRow = (newCityCollectionDataSet.CaseSelectorRow)SelectedRowView.Row;
frmSummary SummaryForm = new frmSummary(this);
SummaryForm.LoadCaseNumberKey(SelectedRow.CaseNumberKey, true, null);
SummaryForm.LoadBRTNumberKey(SelectedRow.BRTNumber, null);
SummaryForm.LoadWaterByAdd(SelectedRow.Num, SelectedRow.Direction, SelectedRow.Name, null);
SummaryForm.Show();
}
You could create an activity table with the userID and casenumber they're currently modifying, and then check it to see if any other user is modifying the same case.
The Scenario:
I have a mobile phone comparing asp.net website which displays deals of various networks. The data about the deals we receive from the networks is in an excel sheet. We import the data from the excel sheets to the tables of each network in our database. Now, the data that we receive is not consistent for every network, as in, a network may name give the phone name as 'curve 8250' and another may give it as '8250 curve' and another might give it as '8250curve'.
Now, we have another module which allows the user to view the deals of a particular handset available on all the networks. To make this module work, what we need to do id make sure that the phone names are consistent for all the networks.
For this, I am planning to make a module for the webadmin which displays the phone names(probably in a gridview) from all the network tables, and the webmaster could edit the phone names so as to make them consistent. The retrieval of the distinct column names from all the tables was easy, and that is done.
The Problem:
Now, the real part is that how can we program the module so that it updates the particular column values in all the network tables. The schema of each table is exactly the same.
Edit: I always forget to add something :# . I know it can be done the hard way, in code behind, running a loop. But is there any simpler, hassle free way out there? like some datacontrol that would make life a bit easier in this situation?
Update:
I tried doing this using code behind. I made a gridview and displayed the data using item templates, and also provided a textbox in a second template. Then on a button click, I'm running this code:
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(ConfigurationSettings.AppSettings[0].ToString());
foreach(GridViewRow gvr in GridView1.Rows)
{
TextBox tb = (TextBox)gvr.FindControl("New Value");
Label lbl = (Label)gvr.FindControl("Old Value");
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
if (lbl.Text != tb.Text)
{
try //updation if primary key constraint is not broken
{
con.Open();
cmd.CommandText = myupdatecommand; /*this is not the actual command that I'm passing, the command I'm passing does contain the values lbl.Text & tb.Text. This is just to make it a better read.*/
cmd.ExecuteNonQuery();
}
catch (SqlException sqe)
{
if (sqe.ErrorCode == -2146232060)//if primary key constraint is broken
{
try
{
//delete the row from the table that contains only unique phone names
cmd.CommandText = deletecommand;
cmd.ExecuteNonQuery();
}
catch { }
}
}
finally
{
con.Close();
}
//Update table2
try //only updation as here the phone name is not a primary key
{
con.Open();
cmd.CommandText = updatetable2;
cmd.ExecuteNonQuery();
}
catch
{
}
finally
{
con.Close();
}
.
.
.
//similarily update rest of the tables
.
.
.
Response.Redirect(Request.Url.ToString());
}
}
When I run the this code, everything happens smoothly, but when we update more than one row in the grid at a time, the updation only occurs for the first edited row, the other edited rows are remaining the same.
I know it must be a very small thing that I'm missing out on here, but I'm not able to proceed further :(
Any help on the matter is highly appreciated. Thanks in advance!
PS- I'm using ASP.Net 3.5, with c# as code behind, and SQL Server 2005 as back-end.
OK, I'm going to assume you are using LINQ-to-Sql, but in theory, it shuoldn't matter, the basic principle is the same.
You will need a collection of connection string, one for each each database. Presumably you already have this.
using (TransactionScope scope = new TransactionScope())
{
foreach (var connStr in listOfConnStr)
{
using (var db = new MyDataContext(connStr);
{
// do update here.
}
}
}
That's pretty much it.
You could pass the "do update here" part in as a lambda function.
To be honest, I'm now embarrassed to answer my own question.
The problem was just that I had mistakenly put the Response.Redirect(Request.Url.ToString());
inside the if loop which itself is inside the foreach loop.
When will I stop doing silly mistakes :|