3

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.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Will Marcouiller
  • 23,773
  • 22
  • 96
  • 162
  • I found out to this post: http://stackoverflow.com/questions/1973651/how-to-create-anonymous-class-with-interface-in-c that an anonymous types properties are readonly properties, therefore there is no way to manipulate the information it contains and persist it to the datastore, except by supplying variables values which could contain the anonymous type properties values after having been processed. As such, I would then consider that there is no way to process such an action except with the given by Anton Gogolev answer, since I wanted a way to persist through NHibernate. – Will Marcouiller Feb 12 '10 at 18:33
  • Otherwise, the idea would be to to either use SQL Syntax or the HQL approach proposed by Anton Gogolev. – Will Marcouiller Feb 12 '10 at 18:34
  • (I didn't remember by heart that anonymous types properties were readonly properties.) – Will Marcouiller Feb 12 '10 at 18:35

1 Answers1

1

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
  • 113,561
  • 39
  • 200
  • 288
  • @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 Feb 12 '10 at 16:24
  • 2
    "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). – G-Wiz Feb 12 '10 at 16:28
  • 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 Feb 12 '10 at 18:39