2011-04-04 53 views
0

我想升级到流利的NHibernate 2.1(内部版本#694)。因此,我也升级到NHibernate 3.0。我遇到了“每个子表”映射的问题,这在尝试检索数据时会导致错误。流利NHibernate的1.2与SubclassMap导致“无行与给定的标识符”错误

这些表和类与现在已弃用的“Joined-Subclass”映射版本一起使用,该映射存在于先前版本的FluentNhibernate中,该版本允许子类拥有自己的唯一标识。

我已经削成码至其最小的部分,所以让我解释,通过代码,它会变得更加清晰:

以下是涉及到的表:

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; } 
} 

下面是相应映射:

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"); 
    } 
} 

下面是测试:

[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(); 
    } 

当执行断言线,该SQL生成是不正确,因为它试图通过FIELD_ID查找,而不是ID的菜单项。因此,我收到错误:NHibernate.ObjectNotFoundException: No row with the given identifier exists[AS.AIMS.DomainModel.MenuItem#11]

首先生成SQL检索userLinks,这是正确的:

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 */ 

然后检索菜单项,它使用的,而不是ID FIELD_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 menuitem0_1_ 
     on menuitem0_.Field_id = menuitem0_1_.ID 
WHERE menuitem0_.Field_id = 11 /* @p0 */ 
+0

流利1.2/nh3.1今天就上线了。 http://fluentnhibernate.org/blog/2011/04/03/fluent-nhibernate-1.2-released – 4imble 2011-04-04 15:44:21

+0

这不是你的完整代码,是吗? menuitem从子类映射到什么? – 2011-04-04 16:08:09

+0

MenuItem是Field的子类。这是在类声明中定义的:'public class MenuItem:Field' – Pat 2011-04-04 16:18:26

回答

1

刚刚看了我是如何做到这一点的,唯一的区别是我可以看到的是在数据库(在你的情况下)MenuItem只会有一个Field_ID。这将涉及到现场的ID。

如果您删除MenuItem上的ID并使Field_ID成为键,它会起作用吗?像这样:

MENUITEM     FIELD 

#Field_ID <----------> #ID 
NavigateUrl    Code   
(Removed Code, Desc)  Description 
+0

因此,我将UserLinkMap中的行更改为:'References(x => x.MenuItem).Column(“Field_ID”);'我得到一个错误,因为它试图从UserLink表中检索Field_ID,这当然会不存在。 – Pat 2011-04-04 16:12:32

+0

对不起,我的意思是在你的数据库中,而不是映射。他们看起来很好。 – 4imble 2011-04-04 16:20:04

+0

Kohan - 感谢您的帮助,这似乎按预期工作。我想我想知道我以前是否有错,或者是否可以用其他方式完成?我想MenuItem表有自己的唯一标识符。我问,因为这个小样本是一个非常简单的真实世界应用程序版本,它的规模要大得多,并且以这种方式对表格和映射进行更改将是一项非常大的工作。 – Pat 2011-04-04 17:04:50

相关问题