Question

Im currently researching how to port the Data Access Layer of an existing .NET 4.0 MVC 3 web application over to an entity framework. There are many reasons, but the primary one being due to thousands of stored procedures, adding just 1 field to a table results in 30 - 50 sproc edits!!

We are using MS SQL Server 2008 R2 and, ideally, we would like to use NHibernate and Fluent for mapping.

I have simplified the problem Im having into a simple example:

Imagine the following 2 tables:

'Products' Table

ID (INT)
DefaultName (NVARCHAR(128))

'Product Names' Table

ProductID (INT)
Name (NVARCHAR(128))
Culture (VARCHAR(10))

The Products table will contain a list of products, each of them will have a default, English, name. The Product Names table will contain the ID of the Product and many translations.

Currently, using stored procedures, we have the following:

SELECT Products.ID,
       ISNULL(ProductNames.Name, Products.DefaultName) AS Name
FROM Products
LEFT JOIN ProductNames ON ProductNames.ProductID = Products.ID AND ProductNames.Culture = @Culture;

Note: @Culture is passed into the procedure

This always ensures a single Product with either a localised name or default (English) name is returned.

My question is: Is this possible to do at the Mapping level of Fluent NHibernate? I have been searching for days on 'How to join on 2 columns', but cant find a solution which works. It would seem odd if this is not possible in such a mature framework?

As an example of what I have been experimenting with:

public class ProductMap : ClassMap<Product> {
  public ProductMap() {
    Id(p => p.Id);

    Join("ProductNames", pn => {
      pn.Optional()
        .KeyColumn("ProductID")
        .Map(p => p.Name);
    });
  }
}

However, this results in the following exception:

More than one row with the given identifier was found: 109, for class: Product

This is because product 109 has 5 translations and thus all 5 cannot be mapped to a single string.

I have managed to use the 'HasMany<>' method to map all translations into a List within a Product. However, this is not what I need.

Was it helpful?

Solution

if the name is readonly then

public class ProductMap : ClassMap<Product> {
    public ProductMap() {
        Id(p => p.Id);

        Map(p => p.Name).Formula("Select ISNULL(pn.Name, DefaultName) FROM ProductNames pn WHERE pn.ProductID = ID AND pn.Culture = '" + GetCUltureFromSomewhere() + "'");
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top