Creating Root Object by Passing a Value

Creating Root Object by Passing a Value

Old forum URL: forums.lhotka.net/forums/t/6296.aspx


Ian posted on Friday, January 30, 2009

Greetings.

I have a Customer object that will contain a list of CustomerInfo objects.  When the user wants to create a new contact for this customer, the UI will do something like:

Customer customer = ....
CustomerContact contact = customer.AddContact();

The AddContact method in Customer is defined as:

    public CustomerContact AddContact()
    {
      return CustomerContact.NewCustomerContact(_customerID);
    }

And in CustomerContact we have:

internal static CustomerContact NewCustomerContact(int customerID)
    {
      return DataPortal.Create<CustomerContact>(new SingleCriteria<CustomerContact,int>customerID));
    }

The CustomerContact object is a BusinessBase object because I want it to load and save itself, but I need to pass in the customerID as it is only allowed to be created by an existing Customer object. 
Where I'm getting hung up is that I don't know how to get the customerID into the Contact object.  Clearly I'm passing the value to the DataPortal.Create call above.  However, the only DataPortal_Create method to override is:

    protected override void DataPortal_Create()
    {
      // TODO: load default values
      // omit this override if you have no defaults to set
      base.DataPortal_Create();
    }

This is the method that the dataportal calls in the CustomerContact object, and it doesn't pass the customerID that I gave it.  So how do I get the customerID value into it?

 

Thanks in advance.

JoeFallon1 replied on Friday, January 30, 2009

You are missing a key concept.

You do not always have to override a DataPortal method.

You can simply overload it.

So create a DP method with the signature that you require and use that instead.

In other words pass in a SingleCriteria (or some other criteira object that has your value(s)) and include tha in your signature. Then just pull the value out on the other side.

Joe

 

 

Ian replied on Friday, January 30, 2009

Yes and I'm sure I'm missing many more key concepts yet.  I'm still at that spot in the learning curve where I can't distinguish between code that I should leave as-is for fear of breaking something, and code that I should change to suit my needs.

But for now I'm off and running again.  Thanks again!

Ian replied on Friday, January 30, 2009

Allow me to pick your brain again, if you will.  I now have a new CustomerContact object created, then this object gets saved to the database.  What I want to do, is update the readonly list of CustomerContactInfo objects inside the Customer object, without hitting the database again.  All the information I need to update the read only list with either new contacts or updated contact info exists in the client computer's memory, so I feel it is a waste of network bandwidth to reload the list from the dataserver.

In the Customer object I have:

public CustomerContact AddContact()

{

CustomerContact contact = CustomerContact.NewContact(_customerID);

contact.Saved += new EventHandler<Csla.Core.SavedEventArgs>(contact_Saved);

return contact;

}

void contact_Saved(object sender, Csla.Core.SavedEventArgs e)

{

// the first time a contact is saved, generate a new info object

// and add it to the list of contacts

CustomerContact contact = sender as CustomerContact;

if (contact != null)

{

// remove the event handler so it doesn't get added again

contact.Saved -= new EventHandler<Csla.Core.SavedEventArgs>(contact_Saved);

// create a new info object and add it to the list

Contacts.AddNewCustomerContactInfo(CustomerContactInfo.CreateInfoObject(contact));

}

}

In the CustomerContactInfo class I have:

internal static CustomerContactInfo CreateInfoObject(CustomerContact contact)

{

// this just simply takes an editable CustomerContact object and creates CustomerContactInfo object from it

CustomerContactInfo info = new CustomerContactInfo();

info._contactID = contact.ContactID;

info._contactName = contact.ContactName;

info._officePhone = contact.OfficePhone;

info._mobilePhone = contact.MobilePhone;

info._email = contact.Email;

info._active = contact.Active;

return info;

}

And in the CustomerContactList class I have:

internal void AddNewCustomerContactInfo(CustomerContactInfo info)

{

IsReadOnly = false;

this.Add(info);

IsReadOnly = true;

}

Everything works except for the Saved event.  Because the event is hooked up to the old CustomerContact object, the ContactID field is still zero.  So somehow I need to grab this ID from the new CustomerContact returned from the DataPortal so I can update the Info object accordingly.

Am I even going about this the right way?  I intend to do a lot of this type of stuff in my application.  My "read only" Info objects are going to be read only as far as the user interface is concerned, but will regularly get updated by the business objects themselves after a save has taken place.  I also get this sinking feeling that read only objects might not call PropertyChanged so the interface might not even know that data has changed.  How do the experts do this type of thing?

JoeFallon1 replied on Friday, January 30, 2009

I do not do this but others may.

One key concept is that when a BO is sent through the Dataportal in 3.6 it is really a clone of the BO in your UI. So there are 2 BOs in play when you call .Save. Your code should always update the reference in the UI so it should be:

myBO = myBO.Save

The other idea is that event handlers have to be re-hooked up when a BO is deserialized (returns from the DataPortal). If you do not re-hook them upon deserialization, they do not run. There are threads in this forum that discuss it.

Joe

 

 

Copyright (c) Marimer LLC