views:

67

answers:

4

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?

+1  A: 

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.

Matthew Flaschen
He can also take all the code from busItem constructor and put it inside try catch block to get more detailed information when error occurs.
virious
A: 

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?

BlueMonkMN
Yeah, the code I posted isn't the actual code, cause it's really big. But the constructor is really working and getting all values correctly
Vitor Reis
I don't believe it. If the constructor can set vItem.Desc without an error, then the other code should be able to set vItem.Desc without an error unless 1) some other code has cleared vItem to null or 2) that particlar constructor never actually ran... for example if you declared a local vItem within the constructor, so it never actually set the main vItem.
BlueMonkMN
You were right, my mistake. The object was being cleared by another method and I didn't noticed
Vitor Reis
A: 

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";
  }
John
A: 

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.

Keith Paul Barrow