What type is my parent

What type is my parent

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


wjcomeaux posted on Friday, December 15, 2006

I have an EditableChild object that is used within multiple EditableRoot objects.

Specifically speaking I have a this structure

Request (of EditableChild), AccessRequest (of EditableRoot), ConcurrentRequest(of EditableRoot), HardwareRequest(of EditableRoot)

So, the Request editable child object has an Update function that requires a parameter object. What type of object do I pass it. I am generating this code with codesmith so right now I am generating the Request object with a parent type of object. However, this breaks the strong typing CSLA gives, does it not? I obviously don't want a different type of RequestObject as that's just silly.

Thoughts?

Thanks, Will

xal replied on Saturday, December 16, 2006

Without goint into the argument of whether that's good or bad, it sounds like the job for an interface.

Create an interface that is capable of returning the values a child would normally use from it's parents (like the id). Then your parent implements that interface, and the child's Update method would take a parameter of type IMyParentType...

Andrés

JoeFallon1 replied on Saturday, December 16, 2006

I agree with Andres.

In ver 1.x I created an Interface named IParent which has a single Property named Key.

Then in any BO which hits the DB and returns an Identity value I know I need to pass the Key to the child BOs so I always pass the Parent BO as IParent and extract the Key from the Interface. This is the only case I have ever come up with for passing the parent as a Parameter. In all other cases I omit it.

Note: Rocky added and IParent interface in Csla 2 - but since they are in different namespaces I should be OK. But I may have to qualify mine after I complete the upgrade.

Joe

 

wjcomeaux replied on Monday, December 18, 2006

Xal:

You hint that this design may not be a good idea? What do you mean and do you have a better approach? I am not tied to doing things this way, it just seems the most logical since I have data and rules specific to all request types (the Request object) and then I have values and rules specific to each type of request.

Would it be better to subclass the request object in this case?

Thanks, Will

xal replied on Monday, December 18, 2006

Well, I usually tend to separate my bo's when they're doing different stuff, even when they seem to be doing pretty similar, which is your case. One size fits all is not usually the best way to go.

So, you could have a generic base class that does most of what you expect it to do, and have different children for each of the root objects. Each of those children would inherit that base class and implement their own methods for Inserting and Updating.
The base class could have a method with a command parameter so that it can add it's own parameters to the command. Like:

Friend Sub Insert(parent as MyActualParent, tr as transaction)
Using cmd as sqlcommand = new sqlcommand("InsertChild",tr.Connection)
cmd.transaction = tr
cmd.Parameters.AddWithValue("ParentId",parent.Id)
MyBase.AddSqlParams(cmd)
cmd.ExecuteNonQuery()
End Using
End Sub


There's really very little you'd have to implement in each of those derived classes...
Perhaps at some point in the future, each of those start having more differences, and you don't really want to start adding:
If parent is ParentType1 Then
do this
else
do that
End if

So, watch out for that, because that's when the app starts getting out of control. Keep your classes small and it's functionality trimmed to what it really needs to do. If you find that you have many different classes that may do the same thing, use inheritance instead of one class that suits all cases.

My 2 cents.

Andrés

wjcomeaux replied on Monday, December 18, 2006

I think we are on the same lines. Here is my current model.
Request - implements all rules associated with a request (requires name, description, request_date, needed_date and a few more things.

AccessRequest : Request -- implements logic specific to access request (what module, director approval)

BugFixRequest : Request -- what application has the bug, describe the bug, major/minor bug, etc.

so on and so forth. It seems like inheritance is the way to go here. I definite have "is-a" relations (AccessRequest IS A Request). I don't anticipate issues where I'll need to do things like "If parent is ParentType1 Then" as all the requests are treated separately except for cases where we will simply be listing all requests in which case we'll simply be querying the Request object and not care about the superclass.

Now another question. How do we get CodeSmith to allow inheritance? Right now is simply assumes the base class from the Csla type... Might be worth another post but I figured I'd ask it here.

Thanks
Will

xal replied on Monday, December 18, 2006

I guess it depends on what you use to generate your code...
I use this: http://groups.google.com/group/cslagenerator

But the truth is that regardless of what you use for code generation you can't use it for every situation... sometimes you have to get your hands dirty...! :D


Andrés

xal replied on Monday, December 18, 2006

But since you're using codegen, perhaps you should ask yourself:
"Do I need these objects to be interchangable??"

For starters, generics will never allow that, so you'd need an interface for that.
Perhaps you should go for just generating different business objects alltogether instead of having a base class.
Probably the parts that are going to be duplicated (other than the properties themselves) are the rules. But you could build those rules separately and add them to all of your classes if you want to.
Sometimes inheritance is used for the sole purpose of saving you from writing the same code twice and not really because you need that. Code generation saves you the pain of that duplicity and makes it easy to maintain it if it ever needs change.

Don't get me wrong, I'm not saying inheritance is bad or that it's not the way to go... Just stating the obvious, which is, if you had done that instead of going with the base class, you would probably have already moved on to doing something else. Wink [;)]

Andrés

wjcomeaux replied on Monday, December 18, 2006

I agree with the get it working part. Our data model has a table for Requests and then other tables for specific information. So we do have a Request, AccessRequest, ConcurrentRequest, etc table all keyed on the RequestID column of the Request table.

To generate right now we are pulling directly from the table based on an ORM. To go with the all in one class approach we would have to pull data from procedures I presume and that's an avenue of CodeSmith we have not yet explored. We also generate our sprocs using CodeSmith so these would then have to be tailored to allow for joins in order to generate the all-in-one objects from them.

I'm honestly not sure how inheritance plays into the sproc generation either but I don't think it imposes any issues. The standard sprocs will still function perfectly fine I think.

Also, the all unique class (without a base class) would make it difficult for me to simply display a list of ALL requests unless I still have a Request object. This is another reason I was looking to inheritance.

Will

 

xal replied on Monday, December 18, 2006

"I can't do this because the generated sprocs won't support it" isn't a good answer...
I have several situations where the generated code is right, but the generated sprocs are not even close to what i need. That's why i always consider generated sprocs as an aid, not a solution.

And the about the "list of requests",
1) First you should consider that that's another use case, and perhaps one where you'll only see data in a readonly fashion.
2) Unless you do go with an interface, you can't do that anyway, even if you have that base class. Generics are not polimorphic and thus, not interchangable. You'd need to have the base class implement an interface, or you could still generate objects separately without a base class and have them implement an interface...

Andrés

wjcomeaux replied on Monday, December 18, 2006

Thanks Andrés

You've been a big help. I think I will see about the Interface which I totally agree with as well as the all-in-one objects. This may provide better performance in the long run anyway as it seems Csla would require at least two trips to the database using inheritance (one for the base and one for the derived class). This may turn out to be a better method overall.

Cheers! Will

xal replied on Monday, December 18, 2006

Not really, I'd normally pass the datareader and the command objects to the base class and do it all in one trip...

Andrés

wjcomeaux replied on Monday, December 18, 2006

Yeah, that is the way the CodeSmith templates currently generate.  However, this poses a question for me.

Right now I have
class AccessRequest : IMyRequest
{
    RequestEC _requestEC;
    ......
}
where the ExecuteFetch function does FetchObject then FetchChildren

So in my database I would do something like

select ar.[x],ar.Yes [Y],ar.Person [Z] from AccessRequest ar where ar.ID = 1
select r.Angel [A],r.Beer [B],r.Coffee [C] from Request r inner join AccessRequest  ar on as.Request_ID = r.ID where ar.ID = 1

This will return 2 resultsets to me AccessRequest object. Now, what happens if I need yet another level on this? If I have a BO that uses a member of AccessRequest. Now I have 3 resultsets coming back from my sproc and I have to keep track of what order they are in? Or is there a better way to handle this? Note: I don't currently see the need for grandchild (or deeper) objects but it is conceivable.

Also, I guess for just child objects I have to generate the code and then write the sprocs against the code. Or attempt to predict the order the child objects will get rendered in the code.

Once again, it seems quite a lot like code generation is only really useful for the most simple cases.

Will

 

xal replied on Monday, December 18, 2006

ok, so you get an x, an "ok" and a little guy from one table, and then you get an angelm a beer and a coffee from the other...
I don't think remoting supports that... Wink [;)]

I'd do a join there and have one result set for that child.

Now, on the subject of grandchildren, this has been covered in length over and over again in this forum, so search on that. Some people usually use datasets, others lazy loading.

What you can do with code gen really depends on the templates you're using, but hey, if it were that easy we wouldn't have a job, would we??!!

Andrés

wjcomeaux replied on Monday, December 18, 2006

All I gave you was x,y,z an a,b,c. How the heck did you get those specifics about my database? My boss is going to kick my databits!

So you're saying you'd return a single datarow for the object in the form of
x,y,z,a,b,c,1,2,3 and have the GetObject function just reference the columns by name and don't do a dr.NextResult to get to the child object (since in reality the object can be represented by a single row using a join? Or do you mean something else?

Will

xal replied on Monday, December 18, 2006

That's exactly what I mean. If your object is a root object, then there's no problem having 2 resultsets to fill it. But if it's a child collection, then you absolutely MUST have that in a join, otherwise you'll never fill you're whole hierarchy...

Andrés

wjcomeaux replied on Tuesday, December 19, 2006

Ok, now for the sake of code generation. Current the templates for CodeSmith do a dr.NextResult() in the FetchChildren function. So I guess now what I should do is add an attribute to my ORM that says something like "UseSameResultForChild = true/false" then change the template to output the dr.NextResult only if that flag is false.

I also see another issue with this now though and that is, what if my parent object and child object both have an ID field. I need some way to resolve the proper ID into the proper object. Any ideas?

I have similar columns all over (CreationDate, Last_Updated_By, TimeStamp)...

Will

wjcomeaux replied on Tuesday, December 19, 2006

Disregard that. I am actually told from our SQL pro here that in many cases doing multiple selects in a spproc is as fast as returning the single massive row and he thinks it would be fine to just use the existing dr.NextResult functionality built into the CSLA templates.

I think we will design along these lines for the time being.

Thanks for all the input Andres,
Will

wjcomeaux replied on Monday, December 18, 2006

Well, it seems that the factory model in Csla (or at least that imposed by the codesmith templates) will not allow inheritance.

Error 3 'RequestER()' is inaccessible due to its protection level

Because the constructor or RequestER is private. So, it I make it available for inheritance, I no longer have an enforced factory here

How are you guys going about this? This would put me back to encapsulation where my
AccessRequest object would simply have a member of type Request.

I can go with protected on the constructor of the Request object. This at least compiles but I'm not sure of the overall ramifications.

Thoughts? Will

Copyright (c) Marimer LLC