List<>.Find(delegate) issue - c#

I have a multi-column combobox where the datasource is a List<> in my Select Class
Select selection = new Select();
RadComboBox1.DataSource = selection.GetAcctUtilCo(e.Text, 10).Skip(e.NumberOfItems);
I have a few DataTextFields. My DataValueField is the AcctID.
Once an account is selected, I need the datatextfield values to populate some fields in a gridview.
I am trying to use the .Find() method by AcctID to retreive the data without success:(
int AcctID = Convert.ToInt32(RadComboBox1.SelectedValue); // *
List<Select> mylist = RadComboBox1.DataSource as List<Select>;
mylist.Find(delegate(SelectTop act) { return act.AcctID == acctID; }); // ** exception here
Label lblAcctNo = (Label)grdAccts.HeaderRow.FindControl("lblAcctNo");
lblAcctNo.Text = mylist.AccountNum;
When I debug, I get 'Object reference not set to the instance of an object' on the indicated line.
AcctID is NOT null when I hover over it. However when I hover over mylist, it says null.
I'm new with the .Find method & I'm really not sure if the problem is with that or with using the datasource of the combobox as mylist source.
Can someone please help enlighten me

Your combo-box's data source is not a list. When you use "as" the result is null if you try to cast to an invalid type, instead of throwing an exception like a standard cast. Since you used the Skip function to create your data source you actually have an "IEnumerable<>".

The problem is caused by RadComboBox1.DataSource - it is not persisted between page requests.
In your code that sets RadComboBox1.DataSource, save a copy of the RadComboBox1.DataSource value in the viewstate. eg. ViewState["RadComboBox1"] = RadComboBox1.DataSource;
In the event that runs your above code, restore the RadComboBox1.DataSource by reading the value from the viewstate. eg. RadComboBox1.DataSource = ViewState["RadComboBox1"];
You should hopefully find the values then persist between requests. Good luck!

Related

Get values from database to textbox

I have a WinForm that have a DataGridView and a ComboBox, allowing users to select a subject (from the database).
cbxSubject.DataSource = dsSched.Tables["Schedules"];
cbxSubject.DisplayMember = "Subject";
...
The DataGridView looks something like this: http://i45.tinypic.com/18gmmu.png I added the DataGridView since I don't know any other way how to get those values from the database. I used a code, something like this, to get the values:
TextBox1.Text = DataGridView1.Rows[3].Cells[1].Value.ToString();
But then I realized that it won't work anymore if there are more than 2 subjects to choose from, because the code is set to get the value on the 3rd row and the 1st cell. So even when the user changed subject, the output value (w/c are then displayed in a TextBox) will still be the same. Are there any other ways to get those values? Please help, thanks.
You can add a comboxbox this way
DataGridViewComboBoxColumn subjectsCombo = new DataGridViewComboBoxColumn();
subjectsCombo.DataPropertyName = "SubjectID";
subjectsCombo.HeaderText = "Subjects";
subjectsCombo.DataSource = dsSched.Tables["Subjects"];
subjectsCombo.ValueMember = "SubjectID";
subjectsCombo.DisplayMember = "SubjectText";
cbxSubject.Columns.Add(subjectsCombo);
I would suggest that you DONT use constants. Rather that using 3 and 1, you need to write some code to find R and C from what the user selects. It should be event driven and you need to re-set the text box on change. I'm assuming you are using an on-change event, but you haven't actually given us that information yet.
here's some pseudocode to get where im going with this
public DataGridView1_SelectionChanged(object sender, ChangedEventArgs e)
{//this might not be the right event, I'll leave it up to you to do your own homework
int R = //Get the current Selected Row;
int C = //Get the current Selected Cell/column;
TextBox1.Text = dsSched.Tables["Schedules"].Rows[R].Cells[C];
///OR YOU COULD DO SOMETHING LIKE THIS
TextBox1.Text = ((DataGridView)sender).SelectedRows[0].Cells[1].Value;
}
//Please note, this is only pseudocode, I dont like doing peoples homework for them.
This should give you a more generic idea/algorithm that you would need. Keeping in mind that this might not even be the best way to go about doing this, but Its what I would recommend based solely on the information provided to us thus far. btw, what have you tried? and can you give us some larger code examples, there might be a rather more simple mistake being made that you haven't shown us so we cant tell you about it :-)
Considering that you still haven't actually asked the correct question, because we dont know WHY you are trying to do what you have stated you are doing, I can't get any more specific than this. GIGO, you have to ask the right question in order to get the right answer.
I'll try to get some of your doubts out of the way:
I added the DataGridView since I don't know any other way how to get
those values from the database
You already have a DataSet called "dsSched" filled with database values. So, no, you don't need the DataGridView. Just fill whatever you want directly from the DataSet:
string data = dsSched.Tables["Schedules"].Rows[3].Cells[1].Value.ToString();
then I realized that it won't work anymore if there are more than
2 subjects to choose from, because the code is set to get the value on
the 3rd row and the 1st cell.
Well, I'm not sure where you are running that piece of code (TextBox1.Text = Data...), but if you are running it on the SelectedIndexChanged event of the DataGridView, then you should get data from the exact row that the user selected (or something, again, I did not understood what you are trying to do).
One thing that I suspect is that you are under the impression that the code:
TextBox1.Text = DataGridView1.Rows[3].Cells[1].Value.ToString();
...is binding the textbox to the value in the row / cell. That's not how this works - the value is retrieved once when the code is run, and then again whenever the code is run again. So you should make sure the code is run when you have to get this value.
EDIT:
I mean, how do I get the value? Like, the PrimaryKey or something?
That's the question! I'm sorry, I was probably deviating. Just set the [ValueMember][1] to the string that describes the value column of the dataset.
cbxSubject.ValueMember = "Schedule ID";
Than you access it using [SelectedValue][2], like:
int selValue = (int)(cbxSubject.SelectedValue);

DataGridView Null Reference Exception

I have a webservice which populates my DataGridView using a couple of webmethods.
Without this code everything works great but I need the picture to change depending on the row selected and the name of the picture will be in a static column that will not change.
What I am trying to do is, in my webmethod, send it a picture name equal to picture1.jpg.
In the windows application I am using this code:
int i;
i = memdataGV.SelectedCells[0].RowIndex;
var pictext = memdataGV.Rows[i].Cells[5].Value.ToString();
pictureBox1.ImageLocation = "C:\\Pictures\\" + pictext;
When the DataGridView first populates everything works fine but when I click on one of my button events it throws an exception on the following line:
var pictext = memdataGV.Rows[i].Cells[5].Value.ToString();
NullReferenceException was unhandled
I tried to debug the code and I added the if statement to the top however does not seem to fix it.
Three possibilities:
i has an incorrect value (-1, for example)
Value at Cells[5] is NULL so when you call ToString() blows up.
Cells[5] does not exist. I.E. maybe it's another index, like 4, for example. The index is zero-based, remember.
Based on your comment, change your line to:
var pictext = memdataGV.Rows[i].Cells[5].Value==null?string.empty:memdataGV.Rows[i].Cells[5].V‌​alue.ToString();
Figured it out for some reason the index 5 was returning null and there was a value in the cell. So I did code to grab the value by the column name which found the value and is working
string pictext = Convert.ToString(selectedRow.Cells["PHOTOID"].Value)

How do I edit/update records from a database using textbox?

I have a problem and I would like your help. I have in my page an edit button and textboxes. I want to edit one single record from the database to these textboxes. I wrote the following code, when I click the edit button then I have the results. The results load in my textboxes. But when I try again to run the page with the same ID for second time then I have this error 'Specified cast is not valid.' What's going wrong? I used int ID=3; to get the 3rd record in this example
protected void Button2_Click(object sender, EventArgs e)
{
DataClassesDataContext cxt = new DataClassesDataContext();
USER_TABLE aChar = cxt.USER_TABLEs.Single(c => c.ID == 3); //gets a single record
fname2.Text = aChar.FIRST_NAME;
lname2.Text = aChar.LAST_NAME;
pob2.Text = aChar.PLACE_OF_BIRTH;
pom2.Text = aChar.PLACE_OF_MARRIAGE;
education2.Text = aChar.EDUCATION;
occupation2.Text = aChar.OCCUPATION;
pod2.Text = aChar.PLACE_OF_DEATH;
String str = aChar.DATE_OF_BIRTH.ToString();
String str1 = aChar.DATE_OF_MARRIAGE.ToString();
String str2 = aChar.DATE_OF_DEATH.ToString();
Why are you doing if (!Page.IsPostBack) in your event handler code?
I'd say that normally an event is only raised upon post-back...
I rarely see IsPostBack used in anything other than PageLoad.
You need to explicitly save your changes to the context
cxt.SubmitChanges();
It appears that you are getting a specified cast exception when fetching your object (using Single). You may want to check the data types between your object model and the database to make sure the object isn't expecting numbers where the database uses strings (or vice versa). Also, check the nullability of your objects and database columns. LINQ to SQL does not support implicit type conversions when binding.
As for why it is working on the first request, but not the second, what has changed between the requests? Also, is the context kept alive between the two requests? Single caches the fetched value and short circuits the query pipeline when the same ID is requested a second time, so with Single you should only see one database request if the context was kept alive. Try using ctx.Log = Console.Out to log your database requests, or SQL Profiler if you have it.

Linq To Sql - Update not being persisted

I am really confused about why an update is not taking place. This is very simple:
int goodID = 100;
DataContext db = new DataContext();
Schedule schedule = db.Schedules.Single(s => s.ID == goodID);
// this wont persist - WHY NOT?!
schedule.Email = txtEmail.Text;
// this does persist
schedule.NumberCourses = 5;
db.SubmitChanges();
I can't understand why the field, Email, isn't getting the value from the textbox. What can I check?
EDIT
I have set a breakpoint and checked the value after assignment. It assigns the textbox value but still no update.
Check what changes will be submitted to the datacontext.
Add a breakpoint just before the db.SubmitChanges() line gets executed and add the following Watch:
db.GetChangeSet();
In the Watch (or Quick Watch) window you'll be able to see which changes are being submitted.
Set a breakpoint and check the value of schedule.Email before and after that line. Also, use the immediate window to check txtEmail.Txt to see if it actually contains data.
Tell us what you find.
Does that dbml match the database table? If it doesn't match the database, you can get weird things. Try reimporting it.
I am an idiot. It's fixed. Votes for everyone.
Instead of checking in the database, like a normal person would, I was just looking on the webform after refreshing the page. I wasn't initializing the textbox with the value from the db. So the update was happening. See? I told you I was an idiot.

Linq-to-Sql SubmitChanges not updating fields ... why?

I posted this question yesterday evening, which has led me to discover a huge problem!
I have a decimal column in my database called Units, anytime I set the value of the column to a NON ZERO, and SubmitChanges the column updates with the new value. If I try to set the value of the column to ZERO, the SubmitChanges does not update the column.
data.Units = this.ReadProperty<decimal>(UnitsProperty);
data.UnitPrice = this.ReadProperty<decimal>(UnitPriceProperty);
data.Price = this.ReadProperty<decimal>(PriceProperty);
I've taken a look at the DataContext log and I can see that the field with the ZERO value is not included in the query. Even if I try to hard code the change Linq ignores it.
data.Units = 0;
data.UnitPrice = 0;
data.Price = 0;
Needless to say this is killing me! Any ideas why this happening?
Solution
I figured out my problem with the help of the SO community. My problem was being caused by the fact when I created my entity to attach, the default value of the column was set to zero, so when it tried to assign the value to zero ... LinqToSql says hey ... nothing changed, so I am not updating the value.
What I am doing now ... just to make it work is the following:
ctx.DataContext.InvoiceItems.Attach(data, true);
That seems to force all the values to write themselves to the database. This works for now.
I have tried to reproduce this with a the following code, but for me it works.
using (DataClasses1DataContext ctx = new DataClasses1DataContext())
{
var obj = ctx.DecimalColumnTables.First();
Debug.Assert(obj.B != 0);
obj.B = 0;
ctx.SubmitChanges();
}
So I think there must be something special in your domain that causes this. I suggest you to create a such simple repro with your domain model and see what happens.
LINQ to SQL ignores updates to the current value, so if the field was already zero, you may not see any updates.
Off: The OR/M you use is LINQ to SQL. LINQ is the name of the querying capability in .NET, but LINQ does not define nor implement any update logic. So the issue relates to LINQ to SQL, not LINQ.
Obvious question, but are you sure the column is mapped in the dbml / mapping file?
Also - is it a calculated column? (i.e. price => units * unitprice)
I figured out my problem with the help of the SO community. My problem was being caused by the fact when I created my entity to attach, the default value of the column was set to zero, so when it tried to assign the value to zero ... LinqToSql says hey ... nothing changed, so I am not updating the value.
What I am doing now ... just to make it work is the following:
ctx.DataContext.InvoiceItems.Attach(data, true);
That seems to force all the values to write themselves to the database. This works for now.
Some more information ... I figured out my problem ... it's more of a lack of understanding about LinqToSql ... where I am doing:
private void Child_Update(Invoice parent)
{
using (var ctx = Csla.Data.ContextManager
.GetManager(Database.ApplicationConnection, false))
{
var data = new Gimli.Data.InvoiceItem()
{
InvoiceItemId = ReadProperty(InvoiceItemIdProperty)
};
ctx.DataContext.InvoiceItems.Attach(data);
if (this.IsSelfDirty)
{
// Update properties
}
}
}
I thought this would load the original values ... what happens is that it creates a new object with default values ... empty values, like 0 for decimals, Guid.Empty for uniqueidentifiers and so on.
So when it updates the properties it sees the Units already as 0 and it sets it to zero. Well LinqToSql doesn't recognize this as a change so it doesn't up date the field. So what I have had to do is the following:
ctx.DataContext.InvoiceItems.Attach(data, true);
Now all the modifications are generated in the update statement whether there is really a change or not. This works ... seems a bit hackish!
The correct answer is as many pointed out to use the special overload of Attach which accepts a boolean parameter to consider it as modified, (make the mistake of using another overload and it simply won't work):
ctx.DataContext.InvoiceItems.Attach(data, true);
Note however that you still might need to have a "Version" column in the table of type "timestamp".
I had this problem and all the suggestions I'd seen didn't apply or work.
But I found I had made a very simple mistake!
When updating the property I was actually calling a custom Set method (because there were other things that needed to be changed in response to the main property in question).
After hours of head scratching I noticed that my Set method was updating the private member not the public property, i.e. this._Walking = value;
All I had to do was change this to this.Walking = value; and it all started to work!

Categories

Resources