Fluent NHibernate 1.2 with SubclassMap causes "No row with the given identifier" error
I am trying to upgrade to Fluent NHibernate 2.1 (Build #694). As a result, I am also upgrading to NHibernate 3.0. I am having an issue with a "Table-Per-Subclass" mapping, which results in error when trying to retrieve data.
Important Note: these tables and classes worked with the now deprecated version of "Joined-Subclass" mapping which existed in a previous version of FluentNhibernate, which allowed the subclass to have its own unique id.
I have whittled the code down to its smallest parts, so let me explain, via code and it will become more clear:
Here are the tables involved:
Here are the classes representing the tables:
public class Field
{
public virtual int Id { get; set; }
public virtual string Code { get; set; }
public virtual string Description { get; set; }
}
public class MenuItem : Field
{
public virtual string NavigateUrl { get; set; }
}
public class UserLink
{
public virtual int Id { get; set; }
public virtual string ExternalLinkName { get; set; }
public virtual MenuItem MenuItem { get; set; }
public virtual int UserId { get; set; }
}
Here are the corresponding Mappings:
public class FieldMap : ClassMap<Field>
{
public FieldMap()
{
Table("Field");
Id(x => x.Id, "ID").GeneratedBy.Identity();
Map(x => x.Code, "Code");
Map(x => x.Description, "Description");
}
}
public class MenuItemMap : SubclassMap<MenuItem>
{
public MenuItemMap()
{
Table("MenuItem");
Map(x => x.NavigateUrl, "NavigateUrl");
}
}
public class UserLinkMap : ClassMap<UserLink>
{
public UserLinkMap()
{
Table("UserLink");
Id(x => x.Id, "ID").GeneratedBy.Identity();
Map(x => x.ExternalLinkName, "ExternalLinkName");
Map(x => x.UserId, "User_ID");
References(x => x.MenuItem).Column("ID");
}
}
Here is the test:
[Test]
public void CanRetrieveUserLinks()
{
ISession session = GetSession();
DetachedCriteria criteria = DetachedCriteria.For(typeof (UserLink))
.Add(Restrictions.Eq("UserId", 1));
ICriteria executableCriteria = criteria.GetExecutableCriteria(session);
var userLinks = executableCriteria.List<UserLink>();
Assert.IsFalse(string.IsNullOrEmpty(userLinks[0].MenuItem.NavigateUrl));
session.Close();
}
When the Assert line is executed, the SQL generated is incorrect as it tries to lookup the MenuItem by Field_ID instead of ID. Therefore, I receive the error: NHibernate.ObjectNotFoundException: No row with the given identifier exists[AS.AIMS.DomainModel.MenuItem#11]
First the sql is generated to retrieve the userLinks, which is correct:
SELECT this_.ID as ID2_0_,
this_.ExternalLinkName as External2_2_0_,
this_.User_ID as User3_2_0_
FROM UserLink this_
WHERE this_.User_ID = 1 /* @p0 */
Then to retrieve the Menu Item, it uses Field_Id instead of ID:
SELECT menuitem0_.Field_id as ID0_0_,
menuitem0_1_.Code as Code0_0_,
menuitem0_1_.Description as Descript3_0_0_,
menuitem0_.NavigateUrl as Navigate2_1_0_
FROM MenuItem menuitem0_
inner join Field m开发者_开发问答enuitem0_1_
on menuitem0_.Field_id = menuitem0_1_.ID
WHERE menuitem0_.Field_id = 11 /* @p0 */
Just looked at how i did this, and the only difference i can see is that on the database (in your case) MenuItem would only have a Field_ID. This would would relate to ID on field.
Does it work if you remove ID on MenuItem and make Field_ID the key. Like so:
MENUITEM FIELD
#Field_ID <----------> #ID
NavigateUrl Code
(Removed Code, Desc) Description
精彩评论