Cemre Mengü
Cemre Mengü

Reputation: 18754

Fluent NHibernate private field mapping

I have generate some fluent NHibernate code. It has entity code like:

    private ISet<CardPlace> _cardPlace;

    public MagazineType()
    {
        _cardPlace = new HashedSet<CardPlace>();
    }

    public virtual ISet<CardPlace> CardPlace
    {
        get { return _cardPlace; }
        set { _cardPlace = value; }
    }

And mapping for this property like:

       HasMany(x => x.CardPlace)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan()
            .Fetch.Select()
            .AsSet()
            .Inverse()
            .LazyLoad()
            .KeyColumns.Add("MAGAZINE_ID");

What I don't understand is the .Access.CamelCaseField(Prefix.Underscore) line. Why is it not being mapped directly to property but instead mapped to the private backing field ? Is there any reason for doing this ?

Upvotes: 1

Views: 1157

Answers (3)

Troy Cox
Troy Cox

Reputation: 41

There are at least a couple of reasons to map to the backing field.

Encapsulation, as metioned by Radim Köhler above being at the heart. But, let me help with some practical examples.

Having a private backing field in the first place can allow that some work may be done when getting the value or when setting the value.

Mapping the DB data to the backing field allows the getter to perform the work that is being done when reading the data and allows the work to be done when setting the data. But, the backing field will be the raw DB data as it is stored.

What sort of work, you may ask? Suppose you are storing data in the DB as a flag....you may translate the flag in the setter to some binary format and then translate it back from the binary format when reading---allowing the property to encapsulate the translation to the raw data that is stored in the DB. Properties could be using the same DB column using logical operations on a binary or integer DB type. Sometimes, you may have a DB that is many years of data and integration with other systems that will not allow you to easily alter the DB format. Your getter/setter can translate it to a format more understandable in your code. You might even perform some encoding/decoding. There are many possibilities.

Encapsulation can also be about complexity.

Suppose many factors go into what is stored into the DB---some complex result of many things in the class resulting from methods and the status of other properties, fields, referenced objects, etc. In such a case you may not have all the logic in the setter. You may have a private setter or no setter at all. Reading the value may still be through a public or protected getter, with some small amount of work. In this case, the backing field has to hold the mapping. You can't allow exposing the setting or the getting to the property when work is required, as someone could easily think they could simply get or set the value directly and bypass the required work to translate the value. They may even attempt to duplicate the work that was encapsulated in the class all over again if the setter or getter were directly mappped to the raw data in the DB.

There are other times when dealing with collections or complex types that you need to translate in the getter or setter. You expose the complex type through the property, but the data gets boiled down to a simple type in the DB. Component mapping can do this as well.

Upvotes: 0

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123851

The answer here would/should/could be: to improve the Domain Model design. The main helper word here would be "encapsulation". Because:

Why are we trying to create our solid model (with all the business/validation rules)...
... while keeping the back door opened, i.e. having public setters.

There is a really nice article, going really deep into that:

Strengthening your domain: Avoiding setters

Let me cite, just from its Summary (but please go through that text)

Aggregate root boundaries are fun to talk about in theory, but many domain models you might look at only have boundaries in name only.
If a domain model exposes operations and commands only to also expose bypassing these operations by going straight to property setters, then there really isn’t a boundary at all.
...
The justification for leaving public setters in place is often expressed in terms of “easier testing”. From experience, invalid domain objects are more confusing and harder to test, simply because you can’t know that you’ve set up a context that is actually valid when using your application.

And all the arguments from the article (read it please) condensed in final paragraph:

We can avoid this confusion and likely extra defensive coding by
removing public setters for data that should only be changed through operations and commands executed on our domain model.
Once again, this is what encapsulation is all about. Our model only exposes what is supported, and disallows what is not.

NOTE: Well, I do use public setters, and I do use "excuses" like "it is better for testing...

Upvotes: 1

nuno
nuno

Reputation: 53

If you remove the

.Access.CamelCaseField(Prefix.Underscore)

the mapping will be to the property getter and setter.

That line is instructing fluent nhiberate to use the field instead.

Upvotes: 2

Related Questions