tags:

views:

130

answers:

3

I have two Linq2SQL objects, Order and OrderLine. An Order contains multiple OrderLines.

I created a constructor Order(Reservation reservation). The idea is that this constructor generates a new order and the orderlines that it should contain.

I have this code:

public Order(Reservation reservation)  {
    this.date = DateTime.Now;
    this.Reserveration = reservation;

    OrderLine orderLine = new OrderLine(reservation);
    //this.attach_Orderlines(orderLine);
    this.Orderlines.Add(orderLine);
}

this.Orderlines.Add(orderLine) results in a NullReferenceException. The same is true when I call this.attach_Orderlines(orderLine)

My guess is that I should save Order first, but how should I do that? I'm not calling Order from my DataContext (which contains a save function)

+1  A: 

Make sure you initialize this.Orderlines. It needs to be an new collection before you can add to it.

public Order(Reservation reservation)  {
    this.date = DateTime.Now;
    this.Reserveration = reservation;

    OrderLine orderLine = new OrderLine(reservation);
    //this.attach_Orderlines(orderLine);
    this.Orderlines = new List<OrderLine>();
    this.Orderlines.Add(orderLine);
}
Kirk Broadhurst
This adds a new NullReferenceException in `this._Orderlines.Assign(value);`
jao
also note that Orderlines is a `System.Data.Linq.EntitySet`
jao
+1  A: 

(Please note: I've completely changed my answer based upon clarification in the comments - Please see history for original answer)

After some discussion in the comments for this question, and subsequent clarification, it sounds to me like, since you are creating your own constructor, you are not initializing the Orderlines property of the Order object.

Note that in the default (parameterless) constructor for Order, there should be a line of code that initializes the Orderlines EntitySet property. Something like:

public Order()
{
    this._Orderlines = new EntitySet<Orderlines>(new Action<Orderline>(this.attach_Orderline), new Action<Orderline>(this.detach_Orderline));
    OnCreated();
}

Your new constructor, when called, does not appear to be creating the internal EntitySet<T> object that is exposed via the .Orderlines property. This seems to explain the NullReferenceException that your experiencing, as your own constructor never calls the default constructor, nor does it replicate the initialization of the Orderlines EntitySet<T> object/property.

The best way to achieve this is to "chain" your constructors such that your overloaded constructor that takes the Reservation object as a parameter first calls the default (parameterless) constructor such that this initialization can take place. This would be achieved using something like:

public Order(Reservation reservation) : this() 
{
   this.date = DateTime.Now;
   this.Reserveration = reservation;

   OrderLine orderLine = new OrderLine(reservation);
   //this.attach_Orderlines(orderLine);
   this.Orderlines.Add(orderLine);
}

Your this.Orderlines.Add(orderLine) line of code should now work correctly (assuming the Orderline orderline = new OrderLine(reservation) line of code does not return null!)

CraigTP
Nope, you do not need InsertOnSubmit.
leppie
@leppie - Care to explain why? The posted code shows using the .Add method on the Orderlines object, which presumably (being a LINQ2SQL question) derives from Table<T>. The Add and Remove methods no longer exist in VS2008 beyond the beta's as clearly indicated in the many links in my answer.
CraigTP
There is no InsertOnSubmit. I'm using .Net 3.5.
jao
@jao - Do your Order and Orderlines classes derive from Table<TEntity>? If so, you should have an InsertOnSubmit method, as detailed here: http://msdn.microsoft.com/en-us/library/bb763516.aspx. Are these Order and Orderlines classes "auto-generated" by the LINQ2SQL designer? (If so, they should derive from Table<T>)
CraigTP
Order and Orderlines derive from `System.Data.Linq.EntitySet`. They are autogenerated by the designer
jao
Based upon the feedback/comments and clarification of the problem, I have completely changed my answer to reflect this updated information!
CraigTP
Thanks a lot. It is working now!
jao
You should still be using OnCreated...
leppie
@leppie - I understand what you're saying, as the default constructor does call the OnCreated() method, however, in this specific example, I think overloading the constructor is a perfectly valid approach. After all, we don't know if the rest of the code may require both a constructor that takes a "Reservation" object as a parameter AND a parameterless constructor also.
CraigTP
A: 

You should add constructor logic in the OnCreated partial method.

leppie