Unhandled Exceptions

04 Aug

Summer of NHibernate Session 07: Exploring m:n Relationships, Views, and Components

I am pleased to announce that I have now posted for download the latest installment of the Summer of NHibernate screencast series.  In this series we explore NHibernate’s support for many-to-many relationships in both our data and our object model, understand how to interact with views, and investigate some ideas about how to leverage NHibernate’s ‘Component’ modeling to help us avoid the ‘primitive obsession’ anti-pattern in our object model.

I also refactor our tests and our data-access-layer to reflect the introduction of the new Name component to our Customer class.

For the record, I am indeed aware that the results of this refactoring as shown in the screencast (that leads to code like Customer.Name.Firstname) represents a clear violation of the Law of Demeter, but I didn’t want to complicate the object model during the screencast.  In a real-world implementation of the Customer class bolstered by the Name class as an NHibernate ‘component’, its likely that this would instead result in a Customer class that looked more like…

public class Customer
{

    //…

    public virtual string Firstname
    {
        get { return _name.Firstname; }
        set
        {
            _name.Firstname = value;
        }
    }

    public virtual string Lastname
    {
        get { return _name.Lastname; }
        set
        {
            _name.Lastname = value;
        }
    }

    public virtual string Fullname
    {
        get { return _name.Fullname; }

    }
    //…
}

…so that accessing the Customer.Firstname and Customer.Lastname properties would pass-thru to the Customer class’ internal Name instance and the Customer.Fullname property would be a read-only pass-thru to the same-named property of the Name object maintained by the Customer.  In this way, consumers of the Customer class need not be aware of the presence of the Name class within the Customer class at all but would still benefit from the ‘richness’ provided by the Name class’ behavior.

Of course, it also now dawns on me that if I had proceeded that way in the screencast, none of the NHibernateDataProvider or NHibernateDataProviderTest methods would have had to have been touched since in a sense the Customer interface wouldn’t have actually changed smile_embaressed.  Just some thoughts to consider~!

Technical Changes

This installment also represents the first that incorporates a few of the technical changes that have been requested by various people in prior feedback:

  • the file format has been changed to wmv (windows media, video) so that (as requested by some) it can be watched @ 1.5x speed in Windows Media Player (hey, whatever works for you –! smile_sniff)
  • I’ve changed my VS IDE font selection from Courier New to Lucida Console; this change should result in the code in the editor being a bit easier to read without my needing to increase the point size at all (and take up too much more screen real estate)

As always, comments, feedback, etc. are appreciated.

25 Responses to “Summer of NHibernate Session 07: Exploring m:n Relationships, Views, and Components”

  1. 1
    Gabriel Says:

    Hello Steve,

    I think there is a technical problem with the sound. On the same PC, no problem from session 1 to 6. But with this session 7, when I put my headphone (Sennheiser PX 100), no sound. I play with WMP11 and tried to VCL same. I have a logitech kit X-530 and without the headphone the sound come from the front only. The others MP3, .avi … work fine. You probably change something ….. If you want to do some sample to test for the next session, you know my email. Regards,

  2. 2
    sbohlen Says:

    @Gabriel:

    That’s what I get for listening to viewer feedback :)

    So that I’m clear on this, am I understanding that you’re reporting that without your headphones the sound comes out of what — your laptop’s built-in speaker but that with the headphones plugged in you get zero sound out of anywhere?

    Its true that I did change the file format (e.g., from AVI to WMV) but when I play the Session 07 file I do successfully get sound on my end (each of two computers I’ve tested on — my laptop with its internal speakers and my desktop PC with its SoundBlaster XFi and extenal speakers). Can you check your cables (and audio settings) and try again for me?

    Also, does anyone else have any issues with the sound in this latest installment –? Please let me know and I can re-encode it if needed, but (and I REALLY hate to say this line as a developer) “It works fine on my machine” :)

  3. 3
    Vinay Says:

    I just downloaded the 7th cast and sound comes out just fine.
    Maybe Gabriel has some problems with his audio. I am using WMP 9. I also played it in VLC and have no problem.

    By the way, thanks a lot Steve, this is one hell of a series. Cant wait until the next.

  4. 4
    sbohlen Says:

    @Vinay:

    Thanks for the positive feedback; I’m glad you’re finding value in the content. Re: Gabriel’s issue, I actually think that in my communicating with him via e-mail directly we MAY have isolated his issue — it seems as though he has trouble when watching this installment in Vista yet its fine under XP so we’re thinking it may either be a difference in the codec under Vista or a difference in the WMP under Vista.

    By chance, are you (or anyone else) having either success or failure listing to session 07 under Vista…?

  5. 5
    Yitzchok Says:

    Works fine for me on Vista.

    Maybe he should try downloading a Vista Codec Pack.

    Did anyone realize that the video is getting a little time shifted at the end?

  6. 6
    Yitzchok Says:

    Time Shifted
    I mean that the sound is not in sync with the Video.

  7. 7
    Marc Scheuner Says:

    Hi Steve - sound is fine here (no headphones), and the change in font makes a HUGE difference for the better - thanks! Can’t wait for the next installment(s)! :-)
    Cheers, Marc

  8. 8
    Gabriel Says:

    Well …

    I received my new hard drive today. Then I have the “chance” to reinstall Vista from scratch. And you know what ? …. the sound is good on the session 7. But I can tell you something : “I didn’t change anything on my machine” :)

  9. 9
    sbohlen Says:

    @Marc:

    Thanks for the extra info (on both the sound and the font). Glad it helps~!

  10. 10
    sbohlen Says:

    @Gabriel:

    Be careful on re-installing Vista; if you re-install your Vista OS more than once a quarter, I think you become an honorary MAC owner :)

    Seriously tho, I’m glad that (something!) fixed it~!

  11. 11
    sbohlen Says:

    For fun, let’s see how close people actually watch these screencasts — can you spot the embarrasing logic error in the CanGetCustomersWithOrdersHavingProduct() test method?

  12. 12
    Michael McGuire Says:

    @sbohlen

    Too scared to point out the errors in case you tell me it was deliberate again :)

    re: errors, iirc you seem to state that SQL doesn’t have updateable views. Which is untrue, the only limitation is that you can only update to one underlying view table at a time(Or use Instead of Triggers to circumvent this)

    With regard to views in general I’d love to hear your opinion on how they fit in with a DDD approach.. views get a bit close to datasets for my liking and overuse may bring some of the same disadvantages. Being new to NH i’m constantly thinking of how I can apply it to existing brownfield projects i’m involved in and of course they usually have many procs and views that bring back columns from multiple source tables, creating a DTO for every one of these seems excessive but i’m sure it’d be more performant than mapping it to single table inspired DTO’s.

    Also can you map DTO to more than one table with NH? (not as a relation but where property a comes from table and and property b from table b)

    Sorry i’m rambling..

  13. 13
    Gabriel Says:

    I have a problem/question with the interaction with Winforms.

    I take the Steve example (Customer and Order) tables. when I get an Customer, I have the customer info and the Orders, this Orders it’s an ISet. In a Winforms application, I’d like display these orders for a specific Customer.

    In the debugger, I see the orders but when I try to bind to a datagridview, this grid view is empty. I tried some suggestions from nhusers google groups but impossible to display theses orders.

    Then I tried to display the full list of Customer (the method return an IList and no problem I see them.

    I may be not use the NHibernate mechanism correctly. I’d like to do a very small application based on steve database and have a classic master/detail, list of customer in a grid, with a grid with all the orders and the customer’s details and ….. how (the best way) to edit/update.

  14. 14
    Artur Says:

    Hi

    I think the CanGetCustomersWithOrdersHavingProduct() test is wrong. It currently tests whether the returned collection has at least one customer with orders with given product, however, it’s meant to assert that all returned customers have orders with that product.

    And a question: As I understand, each customer returned from GetCustomersWithOrdersHavingProduct() will not have a list of all its orders, just the ones that contain given product, am I right?

    Thanks for great series and thanks for changing the format to WMV, playing it at higher speed can sometimes be helpful.

  15. 15
    sbohlen Says:

    @Artur:

    You are correct — that’s indeed the error. We’ll correct in step 1 of the next installment :)

    To your question, actually NO, the way its written presently will return CUSTOMER objects (that’s why ‘typeof(Customer)’ is specified as the initial CreateCriteria call) that satisfy the condition. These CUSTOMER instances have collections of ALL their orders. That’s one of the differences between NHib traversing object collections vs. JOINs in SQL.

    To get just the ORDERs that have PRODUCTs matching the constraint would require re-writing the query in one of a couple of ways, the most obvious would be to do CreateCriteria(typeof(DataTransfer.Order)) and then traverse from the ORDER objects to their related CUSTOMER instances, but there are a large number of other ways to achieve this too.

    PS: Glad you’re liking the WMV format.

  16. 16
    tab Says:

    Steve,

    thanks a lot for this great series. Very clear and understandable all the way through. For me, the learning by example method is very effective. Sure, there’s a lot of details that’s needed before one is an expert NH user, but this kickstart is invaluable.

    It well deserves a donation!

  17. 17
    sbohlen Says:

    @tab:

    Thanks for the feedback; as you suggest this series isn’t designed to cover everything one needs to use NHibernate EVER, just the foundational basics needed to get people able to effectively use it in perhaps the 80%-case. Further learning from sources a lot more comprehensive that this one are definitely proscribed for anyone serious about NHib in their app.

  18. 18
    Nicolas Says:

    Steve,
    Fantastic series!!!

    I think there is an error on the view; it seems your SQL is joining c.CustomerID with o.OrderId, instead of using o.Customer

    Regards,

    Nicolas.

  19. 19
    sbohlen Says:

    @Michael:

    Sorry took some time to reply, but I missed your comment there — I try to reply to most all of them but somehow overlooked yours.

    Re: updateable views in SQL Server, yes you’re correct that this is possible, but it sort of flies in the face of most practices and certainly isn’t DB-portable (which is why I tend to shy away from it as a practice). You are correct that my statement on its face is indeed in error (or at least misleading :) )

    Re: Views in general as they apply to DDD, clearly there’s not MUCH need for a domain Entity that’s normal use is read-only so generally views tend to have no place in the representation of domain entitties but I have used them in the past in some corner case situations. They remain a tool in my toolbelt though one that is less-often implemented.

    Re: mapping DTO to more than one class NOT as a relation, there isn’t QUITE a way to do this in NHibernate though there SORT OF is. If by ‘not as a relation’ you mean ‘not as a collection within the object model’, then YES this can be done useing the mapping tag and its semantics. But if you by ‘not as a relation’ you mean ‘where this isn’t a relation between the two tables in the database from which the values come’ then, NO, since there would HAVE to be some way for NHib to traverse from the record with Identity in the first table to the related single record in the second (or third, fourth, fifth, etc.) table. Again, google on to get a sense of how one might accomplish this and also look around for info on ‘table-per-subclass’ inheritance modeling as this is sort of the same area of focus.

    Hope this helps.

  20. 20
    sbohlen Says:

    @Michael:

    Seems that the angle-brackets from my prior comment (#19) were stripped out of the comment. The mapping tag that I was TRYING to suggest you investigate there is called ‘joined-subclass’. In the prior post, every time the sentence doesn’t seem to make sense, insert the text ‘joined-subclass’ into the sentence and it will be fine :)

    Wordpress seems to want to strip angle-brackets out of comments, presumably to protect me from aberrent HTML entered as comments.

  21. 21
    Nisar Khan Says:

    hi Steve,

    if i understood correctly the purpose of using “view” is for “read only”?

    great videos and learn a lot and today whole day i was watching your videos and i’m on 8th video now ;)

  22. 22
    sbohlen Says:

    @Nisar:

    You are correct (sort of). Various DB platforms have varying support for what are called ‘updateable views’ where you can actually use a view as a read-write target instead of just a read-only target. Different DB targets impose different constraints on what must be ‘true’ for a view to be updateable and still other DB platforms don’t support updateable views at all.

    Given all this, unless you are 100% certain of the DB your NHib-based app will run against, its really best-practice not to make a design decision (like to depend on updateable views) unless you are willing to sacrifice DB-platform-neutrality (one of the main reasons for selecting and O/RM tool like NHib in the first place).

    That said, if you decide that tying your solution to a particular DB target is OK for your app, then google on NHibernate + + “updateable view” and you will certainly find plenty of info out there.

  23. 23
    sbohlen Says:

    @Nissar:

    In comment #22 Wordpress stripped out my thing-in-anglebrackets in that last sentence that was supposed to read “NHhibernate + your-database-here + updateable view”.

    I keep forgetting that Wordpress just drops anything that contains HTML-style angle brackets :)

  24. 24
    Billy Stack Says:

    Hi Steve,

    This screencast touches immutability a little so here is the most apt place to ask the following question:

    I am currently tasked with introducing NHibernate into our codebase. All of our business domain objects are immutable and take the following format:

    public class SampleEntity
    {
    public readonly int SampleProperty;
    public readonly string SampleProperty2;

    public SampleEntity(int sp1, string sp2)
    {
    this.SampleProperty = sp1;
    this.SampleProperty2 = sp2;
    }

    From what I can see, we would have to perform the following to make our entites NHibernate compatible but as close as possible to still being immutable “enough”:

    1. Add a default constructor (it can be private but still needs to be added)
    2. Take the readonly attribute off all properties and have get; private set; accessibility.

    Is there any way to get NHibernate to work with an antity of the type described above?

    In my opinion, we shoudnt have to sacrifice our business domain objects “immutability” to cater for an ORM integration.

    Also, I know another solution could be to map our immutable business domain entities to NHibernate compatible entities but this in my opinion would be too costly!

    So in conclusion , is there a way to get HNibernate to work for “truely” (i.e. using readonly properties) immutable types?

  25. 25
    sbohlen Says:

    @Billy:

    You are (I think) in luck. Step 1 you have already identified as being to make the default (empty) constructor private. Step 2 however is to do something that I didn’t begin to go into in any of the screencasts: tell nhib to use the private backing fields for your properties instead of the properties themselves.

    You need a combination of access=”field” on your property, id, etc. tags and also investigate ‘naming strategies’ so that nhib can properly deduce the name of your backing fields from your property names. This set of steps will allow nhib to access your underlying private data members NOT via your property accessors.

Leave a Reply

© 2008 Unhandled Exceptions | Entries (RSS) and Comments (RSS)

GPS Reviews and news from GPS Gazettewordpress logo