views:

159

answers:

1

Instinctively, I would say that this is impossible, as NHibernate needs to know some mapping information on how to persist a given type. Thus, I encountered some situations in which I could use such a feature. For instance, through a named query or something like so. On the other hand, using a named query would require me to make an addition to the configuration file.

Let's suppose we have an application interacting with some underlying datastore. This datastore is configured through the NHibernate configuration file. Then, I wish to have NHibernate load only a subset of an entity properties, from another subsystem to which my application shouldn't need to interact much, so it is not worthy to define classes for this system, as I only need a fraction of this alien system's information, let's say three out of thirty-two data columns. For that matter, if I chose to load only those three columns let's say for performance concerns, I would then use an anonymous type, perform the required action onto this information, then persist it back to the datastore. Now, it wouldn't be of much interest to do so if I only had one entity to get loaded from the datastore, so let's say I have about 75,000 rows to load into my process. I then shall consider this subset option very seriously!

What strategy should you choose in such situation, if you needed to persist these changes to a subset only of this entity's properties?

FYI: I am asking because I must write specific rules of usage with NHibernate, such rules that even a beginner developer would even be able to use it without knowing too much about NHibernate, but only following the rules and guidance of the technical documents I have to produce.

Thanks in advance for any comments and answers.

+1  A: 

There are two approaches to this.

First, if you need to select entities and do not intend to persist them back to the DB, you can use select new HQL construct. Thus you'll be able to specify which properties to load from the DB.

Second approach is a bit more complicated and is better illustrated with the following example.

Suppose you have Images table, which, naturally, contains images. It has Length, ContentType, CreatedOn, Content, Description and other columns.

In some parts of your app you may want to just edit image metadata without actually displaying image itself. Therefore, for performance reasons you need to load just metadata portion. You will, however, will eventually be saving this to the DB, so the select new approach won't work. What will work, though, is this:

class ImageMetadata
{
    public string ContentType { get; set; }
    public string Description { get; set; }

    // Etc
}

class Image : ImageMetadata
{
    // To native English speakers out there: is it "Content" or "Contents"?
    public byte[] Content { get; set; }
}

Here, you'll have to map both classes to the same underlying DB table and just load either ImageMetadata or whole Image depending on the situation.

Granted, this doesn't scale very well, but it can save you from lots of perf problems.

As for 75 000 entities: ORMs are not for mass updates.

Anton Gogolev
@Anton Gogolev: This is a brilliant approach, and sure a good alternative to the situation stated in my question, though defining a base class like ImageMetadata, and inheriting into the Image object, makes it ImageMetadata a now known type. But what if I obligatory needed an anonymous type? I know this sounds a little exagerated, as one may meet this situation perhaps rarely. Despite, would it be considered a good or a bad practice if I would declare such a subset class into the class that requires using this anonymous type within a method?
Will Marcouiller
"Content" is correct. You are referring to the content of a single image. "Contents" is used when the nature of what you're referring to is a collection that is contained into a single item (table of contents, contents of the refrigerator).
gWiz
Another alternative would be to declare a private nested type within the current class object to contain the data retrieved from the other system's database. This being said, no matching mapping file would be defined, so I guess the best way would be to opt for the HQL construct.
Will Marcouiller
@gWiz Thank you!
Anton Gogolev