Hi!
Ok,I have a Client object as root, it has a contactcollection(editable list child) and now I want to add a new contact (editable child) so I do like this:(as I understand you can not call save on a child object directly)
MyClient.ContactCollection.BeginEdit();
Contact myContact = MyClient.ContactCollection,AddNew();
//Fill myContact
MyClient.ContactCollection.EndEdit();
MyClient = MyClient.Save();
Now the issue is I use Identity column as my PK in database(it generates and increaments by DB engin)
It means when I create a new Contact Its ContactID is 0 and after that I have inserted it in DB it returns identityID.
But how can I get that identity value because it is internally inserted by Client object(root object)
I mean If I insert a new Client I get back new identity like this:
Client myClient = Client.NewClient();
myClient = myClient.Save() // now myClient has the identity from DB
But in case of child objects how I can do that because it is saved internally by root object.
I hope somebody shows me the way that it is done.
Regards
I am assuming you are using Stored procedures in your database to Select/Insert/Update and Delete your data.
The problem is not in your class but in the sp that saves the data. It should return the new id as a part of it. I have included an example, the bit your interested in is the final select statement. This sets your OUTPUT parameter @id to the value of the ident column.
CREATE
PROCEDURE [dbo].[usp_task_insert]@id
int output,@lastupdate
timestamp output,@name
varchar(50),@description
varchar(255)AS
INSERT
INTO [dbo].[TBL_TASK] ([name]
,[description]
)
VALUES (@name
,@description
)SELECT
@ID = [TASK_ID], @lastupdate = [lastupdate]FROM
[dbo].[TBL_TASK]WHERE
TASK_ID = SCOPE_IDENTITY()Thanks for the reply.
But that is not my problem my SP is correct and returns the identity value created by DB in a output parameter and ...
The issue is that for a root editable object when you do :
Rootobject _object = RootObject.NewRootObject();
_object = _object.Save();
now I have the identity value in _object.Id property but in case it is a child object how I can get back a child object with the identity value:
ChildObject _child = _root.ChildCollection.AddNew();
_child.Name = "nnn";
_root = _root.Save()// now my child object is inserted in DB but here I have no reference to newly inserted childobject with new identity value to bind to win form!
I mean inserting new child object is a common and basic thing so CSLA approch must have a correct way to do this not like now go and find in childcollection and find a child with max Id and return that because it would be simply stupid way and not the elegant OO way that CSLA is about.
I really hope somebody answer to this .
Regards
Thanx for your post but it is not related to my problem as I understand.
When I( as a UI developer) create and insert a new child object how I can find out which of object in childcollection is that newly inserted object.
You have a form, user fylls in and pushes the Insert button on the form, CSLA library inserts the child object, but you need a reference to newly inserted child object to bind it to the form so user can see the identity value returned from DB on the form and countinue with his editing job.
My Csla Library works just find. It is not the issue. My question is how UI developer that uses my CSLA library, can insert a child object and return a reference to newly inserted child object?
I am not sure if I understand correctly but after AddNew you get a reference to a new child object that is new so it's PK(a identity column i sql server) is 0 so you must insert it into the database - it means you must call rootobject.Save() and my problem is here after you call rootobject.Save() you get back a reference to rootobject and not a reference to that specefic child object that you have inserted so you can read it's assigned identity id.
I think this is a very basic operation-adding new child object to a database that uses identity columns as PK- so theĀ“re must be a clean and correct OO way to do that.
I am a little bit supprised that such basic thing is so difficult to figure out .
Regards
I'm not sure if this is what you're looking for, but I'll give it a stab. I needed to do this and put this into my Update method on the child in the BO:
// either adding or updating
In the UI, rebinding or refreshing the form may be necessary to show the new value, but it works.
In this case, the UI is calling for a list to select the Contact and adds it to the collection by ID and ParentID. However, if the contact they want to use is not present, I give them the opportunity to add them by calling up the new contact editor and, in a similar way, get the new id for the contact I just created.
In the case of calling a stored procedure to retrieve an new ID, I did this in an event in the UI:
//
string
The myID value is a new contrivance constructed in the Db., the MainForm.MyID is the ResourceID of the person requesting the new programID (for history).
Those are the two instances I've used.
_E
It is not a good idea to first insert a blank line into DB to get back a Identity and then ...
What if user change his mind and click cancel It means you must go to DB and do a delete too!
How the UI developer get access to assigned identity value? This is a simple question and common, it is impossible to do any application and not to need do this but no explanation in book nor in the forum.
I must ask this question from the author that what is the point with this csla because apparently it doesn't make thing easier nor faster, a lot of code to just make things harder?
I mean why not use a typed dataset and you get all of it generated by Visual studio or a orm and so on.
Thanx for your reply.
I have actuelly read the book twice and nothing useful about my above problem.
In case you have read the book I would be very glad if you tell me how is the book,s solutuion to above problem.
Regards
I am having trouble understanding the exact problem, but I think it is this:
So far this is covered in the book, and is illustrated by the Resource class in ProjectTracker, with the notable exception of #6.
CSLA doesn't support #6, and can't, because Save() returns a new object graph. You must update all references to use the new object graph.
I agree that this is not ideal, but it is what it is.
If you have many references to your objects scattered throughout your code (probably because you aren't using data binding) then the issue becomes one of notification - somehow the holders of all those references need to know to update themselves to use the new references.
Child objects can't provide this notification, because (on the client side) they aren't responsible for their own lifetimes. But the root object can provide the notification. In your Save() method you can raise an event (which you must declare as discussed in Chapter 3) along this line:
public override Customer Save()
{
Customer tmp = base.Save();
OnObjectSaved(this, tmp);
return tmp;
}
The onObjectSaved() method raises some event (perhaps ObjectSaved), allowing listeners to be aware that "this" has been replaced by "tmp". In your UI layer you can then use an observer pattern or something similar to spread the news that the old object graph is now obsolete.
Copyright (c) Marimer LLC