Sorry about the title, I don't think I could explain it right:
This is a simplified example class, this is working ok. (I also have a Save() method)
public class busItem
{
public Item vItem;
public busItem(int pItem_Id)
{
DBDataContext db = new DBDataContext();
Item vItemQuery = (from i in db.Items
where i.Id == pItem_Id
select i).FirstOrDefault();
vItem = new Item();
vItem.Id = vItemQuery.Id;
vItem.Desc = vItemQuery.Desc;
}
}
And this is my code-behind call:
busItem item = new busItem(1);
item.vItem.Desc = "new description";
the problem is that when I try passing the "new description", i get a "null reference" exception. How can I do that?
First of all, that code doesn't look right for at least 2 reasons. pItem in the query is not declared; did you mean pItem_Id? Also, the line with "new description" doesn't end with a semicolon. Unless I'm looking at the exact code you have, there's a good chance the actual problem win't be visible. Secondly, I suspect the error is not actually when you assign "new description" but when you assign vItem.Desc = vItemQuery.Desc. I don't see how the "new description" line could be a problem, but if the query returned null because it couldn't find the requested object, you'd get an error when trying to get the original/default description.
Edit: Are you sure you didn't exclude some significant piece of code like declaring a local instance of vItem within the constructor?
You're probably getting the null reference exception in the constructor. FirstOrDefault()
can return null if there are no items in the IEnumerable
, in which case accessing Id
and Desc
will cause an exception. If the constructor completes normally, item.vItem.Desc
shouldn't fail.
I took the code Vitor posted and added two small mock implementations for DataContext and Item so I have running code. Then I added the code that fails in a test. The test passed no matter what I do with the Item object I add to the collection returned by the DataContext.
The only exception I was able to reproduce occurred in the constructor. The line where the new description is set never failed.
I have added my code below.
On a more general note: Public member variables are generally a sign that the design can be improved. I'd suggest to make this variable private and work from there. In our team we have a rule that member variables cannot be public as they lead to weak designs. Just my two cents.
public class Item {
public int Id;
public string Desc;
}
public class DBDataContext {
public System.Collections.Generic.List<Item> Items {
get {
var items = new System.Collections.Generic.List<Item> {
new Item {
Desc = null,
Id = 1
}
};
return items;
}
}
}
public class busItem {
public Item vItem;
public busItem(int pItem_Id) {
DBDataContext db = new DBDataContext();
Item vItemQuery = (from i in db.Items
where i.Id == pItem_Id
select i).FirstOrDefault();
vItem = new Item();
vItem.Id = vItemQuery.Id;
vItem.Desc = vItemQuery.Desc;
}
}
[Test]
public void TestBusItem() {
busItem item = new busItem(1);
item.vItem.Desc = "new description";
}
The problem is probably this code:
Item vItemQuery = (from i in db.Items
where i.Id == pItem_Id
select i).FirstOrDefault();
FirstOrDefault will return the first item, or the default. As Item is a class, the default value is null, and you can't set a member on a null.
You need to to test for null after the above statement, if it is null, instantiate manually.
Also, a public field like that is a very bad idea.