ORM and NHibernate concepts

by andrei 3. October 2008 22:11

You can read about the purpose of this list and how to use it here.
Also, the list of resources is here.

 

  1. general implementation
    B4
  2. concepts
    1. other orms
      code & implementation
      E1
      E2
    2. things to avoid
      1. n+1 selects
        Yet another classic problem is that of n+1 selects. Assume you fetch all Orders in the database and that OrderLines are Lazy Loaded. Then you touch each Order and its OrderLines. Then there will be a new SELECT issued for each Order's OrderLines. If you don't use Lazy Load, the problem will be smaller, but then you run the risk of getting into the problem just mentioned of fetching too much in some scenarios.
        resources
        B4
      2. reading way too much
        A fifth is the "reading way too much" problem when too many complex types are read even though just a tiny amount of information is really needed. This is especially common if you haven't used a somewhat careful Aggregate design and haven't used Lazy Load.
        resources
        B4
    3. mapping
      1. discriminator
        If we assume that Customer and Vendor inherits from Company, the mapping information could look like this:
        <discriminator column="Type" type="AnsiString" length="8"
        not-null="true" />
        resources
        B4
      2. inheritance
        NHibernate supports all three different inheritance solutions, namely Single Table Inheritance, Class Table Inheritance, and Concrete Table Inheritance
        resources
        B4
      3. unsaved-value
        resources
        B4
      4. N:1
        code & implementation
        B4
        resources
        B4
      5. 1:N
        code & implementation
        B4
        resources
        B4
      6. value objects
        NHibernate uses the word component for describing an Embedded Value
        code & implementation
        B4
        resources
        B4
      7. private fields
        For example, you often expose something slightly different in your property get to what is stored, or you do some interception on get/set. In these cases, you need to map, for example, the private field instead.
        code & implementation
        B4
        resources
        B4
    4. entity lifecycle
      resources
      B4
    5. lazy load
      If you do want to use (automatic) Lazy Load Fowler PoEAA with NHibernate, that's easily done
      resources
      B4
    6. scalar queries
      Scalar queries are especially useful in situations where you find it too expensive to fetch complete Customer instances but want a more lightweight result, and you don't want to define a class.
      Of course, the result won't be typesafe in this case, but you could use a variation, namely the one I talked about earlier in this chapter called report query (or a flattening query).
      resources
      B4
    7. report queries
      the result won't have Customer instances, but CustomerSnapshot instances. For it to work, you need to provide a matching constructor on the Value Object (CustomerSnapshot in the previous case) and to mention CustomerSnapshot in a mapping file via an import directive
      resources
      B4
    8. transactions
      Support for manual transaction control is pretty good in NHibernate. There are situations where you might be taken by surprise if you don't watch out (for instance, when you execute a query in the middle of a transaction, NHibernate will then Flush() changes to the database before executing the query). That's a tradeoff between querying not going "through" the cache or ordinary transaction control. The good news is that it's controllable by your code.
      What you do is grab an ITransaction instance, which you can then use to make either a Commit() or Rollback() (Commit() will by default automatically do a Flush()).
      I prefer to control the start and end of the unit of work in the consumer, outside of the repositories
      resources
      B4
    9. caching
      Advanced caching is one area where NHibernate isn't really up to par when compared to Hibernate, but I think it's rapidly becoming better. On the other hand, to me that's not usually a big deal. There are many problems with second-level caching, so that option is often ruled out.
      resources
      B4
    10. unitofwork
      NHibernate uses the Unit of Work pattern Fowler PoEAA as well, and again it's dealt with in the ISession.
    11. query
      1. Criteria objects
      2. HQL
        it's not table names but classes that are used in HQL
        resources
        B4
        1. joins
          data is fetched from two tables, and there is no mention about that in the from clause (that is, there is no join). Of course, the mapping information is used to determine what needs to be done at execution time with the HQL query.
          select o.Customer.Name, count(*) from Order o group by o.Customer.Name
          resources
          B4
    12. session
      1. clear
        to clear the Identity Map from all instances
        resources
        B4
      2. evict
        What you can do to force a database jump (instead of opening a new ISession) is to call Evict() on the instance by saying that you don't want the Identity Map to keep track of the instance any longer.
        resources
        B4
      3. flush
        It is also important pointing out that the INSERT is delayed and won't happen when you say Save(), but rather when you say Flush().
        resources
        B4
      4. saveorupdate
        I could have called SaveOrUpdate() instead, and then NHibernate would have decided on its own whether it should be an INSERT or an UPDATE. The information used in that case is the value of the Identity Field, and it's compared to what you indicated for unsaved-value in the mapping file ("00000000-0000-0000-0000-000000000000" in the case of Guids). If the Identity Field matches the unsaved-value, it's time for an INSERT; otherwise, it would be an UPDATE.
        resources
        B4
    13. identity
      1. don't set it manually
        Normally, you would give Identity Fields default values, such as Guid.NewGuid(), but that's not a good idea if it's possible to avoid it when you use NHibernate because NHibernate uses the Identity Field values to determine if it should be an UPDATE or INSERT. If you provide a default value (unless you set it to unsaved-value, of course), NHibernate will always expect UPDATE if you don't explicitly provide guidance. (You can also use the version tag for signaling INSERT/UPDATE.)
        resources
        B4
      2. guid identity
        In the case of the guid, you can generate it in all the layers, but it's recommended that you do it in the O/R Mapper
        resources
        B4
    14. repository
      the consumer injects ISession instances to the repositories
    15. interceptor
      yet another NHibernate interface
      To use a custom IInterceptor implementation, you provide it as a parameter when instantiating ISession
      resources
      B4
    16. validation
      NHibernate has an IValidatable interface that will get calls by NHibernate at Flush().
      But then I need to reference the nhibernate.dll in the Domain Model, so I prefer a solution like the one I used in Chapter 7, "Let the Rules Rule." I mean, I can use an IInterceptor
      resources
      B4
    17. concurrency
      NHibernate deals with Optimistic Offline Lock if you add a <version> tag to the entities
      resources
      B4
    18. identity map
      NHibernate uses an Identity Map on an ISession level.
      resources
      B4
    19. embedded resource
      If you want the metadata to be within the assembly, don't forget to set the property of the XML file to be an Embedded Resource.
      resources
      B4
    20. generate database from mapping
      I prefer to start with the Domain Model, then write the mapping files, and from that automatically generate the database from the mapping information
      code & implementation
      B4
      resources
      B4
    21. sessionfactory
      What you then try to do just once per application execution is to set up a SessionFactory. The reason for not creating several is that the cost is fairly high. The SessionFactory will analyze all metadata and build up memory-based structures for that. As you might guess from its name, the SessionFactory is then used for instantiating new instances that implement ISession.
      code & implementation
      B4
      resources
      B4

 

You can find the entire list of techniques in progress in the Development base concepts category. Please feel free to leave any comments or suggestions which could make these lists more useful for everyone.

Also, if you are interested in learning these skills you can try the Developer training modules.

 

 

 

Enjoy programming!

 

I am putting together a set of concept lists for the main programming techniques, which should help developers learning or using them to be more efficient. Here are the techniques in progress:

Please feel free to leave any comments or suggestions which could make these lists more useful for everyone.

 

 

Also, if you are interested in learning these techniques you can try the developer training modules.

Again, please feel free to leave any comments or suggestions which could make the training modules more useful for everyone. We are having great results with them at Akcedo (so they really work), but they can always be improved. Also, if you would like to use the modules or are already using them and you want to discuss about the process feel free to comment and ask questions here.

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.4.5.0