i’m trying to upgrade an old CMS to use NHibernate and can’t deter from the original database structure much. Here is the bit which is causing an issue. Say i have the following 2 tables:
Articles:
- Id (PK, Identity)
- Title
- Content
Meta:
- ArticleId (PK, FK to Articles)
- Description
- Keywords
I have created the following classes:
public class Article {
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual string Content { get; set; }
}
public class Meta : IComponent {
public virtual string Description { get; set; }
public virtual string Keywords { get; set; }
}
public interface IComponent {
}
Usually the Meta would normally be mapped as a component (or a one to one relationship) property on the Article class. However in the application i’m building an admin can enable/disable the components that apply to articles. Also i’d like them to extend the application to add their own components without touching the Article class.
For them reasons i can’t add a property against the Article class. Now ideally in my code i’d like to be able to say:
var articles = session.Query<Article>()
.Fetch(a = a.Component<Meta>())
.Where(a => a.Component<Meta>().Keywords.Contains("Some Word"))
.ToList();
// This wouldn't generate an extra SQL statement
var keywords = articles[0].Component<Meta>().Keywords;
Which would generate the following SQL (or similar):
SELECT * FROM Articles INNER JOIN Meta ON Articles.Id = Meta.ArticleId WHERE Meta.Keywords LIKE ‘%Some Word%’
Is it possible to map the Component method so that it does an inner join to get the Meta. The concept seems pretty simple but i don’t have a clue where begin. I’d really appreciate the help.
Thanks
Given this:
AFAIK, you cannot Fetch something that isn’t part of an entity. So from your example, it’s not possible to fetch Meta from the Article entity.
So if you want to fetch the other info of an Article, you just have to join Article to them, then project the complete data in your Linq, example:
Resulting query:
Another approach, start from Meta, then fetch the Article; on query, this will join the Article immediately, i.e. no lazy loading:
Resulting query:
To keep an Article having only one Meta, put a Unique on Meta’s reference: