两个表之间的简单关系

时间:2011-01-12 19:32:18

标签: nhibernate mapping key one-to-many

我今天开始使用NHibernate,但我无法弄清楚如何设置两个表之间的简单关系。我真的不知道它叫什么,它可能是一对多或外键关系(我不是那个数据库设计和使用的术语),但这是一个非常简单的例子。

我有一个表具有属性Id(PK),ProductName和CategoryId的产品。然后我有一个表类别与属性Id(PK)和CategoryName。

我创建了这些类:

public class Product
{
    public virtual int Id { get; set; }  
    public virtual string ProductName { get; set; }  
    public virtual int CategoryId { get; set; }  

    public virtual Category Category { get; set; }  

    public virtual string CategoryName  
    {  
        get { return this.Category == null ? String.Empty : this.Category.CategoryName; } 
    }
}

public class Category  
{  
    public virtual int Id { get; set; }
    public virtual string CategoryName { get; set; }
}

换句话说,我只是想让Product存储它所属的类别(通过CategoryId属性指向Categories表中的Id)。我需要Category类来保存相关产品列表,如果这样做更简单。

为了让我更清楚我追求的是什么,这是我期待的SQL:

SELECT Products.*, Categories.*
FROM Products INNER JOIN Categories ON Products.CategoryId = Categories.Id

至少我认为它应该是这样的(再次,我在数据库设计或查询方面并不擅长)。

我无法弄清楚我需要哪种映射。我想我需要将它映射到Product.hbm.xml文件中。但是我也映射了CategoryId吗?我如何映射Category属性?

似乎我需要“一对多”关系,因为每个产品有一个类别(或者这个推理是否落后?)但似乎没有一对多的映射... < / p>

感谢您的帮助!

增加:

我尝试在Person映射中添加多对一关系,但我不断收到“创建代理失败”的异常,并在内部异常“找到模糊匹配”中。

我应该提一下,我使用的是旧版本的NHibernate(我认为是1.2),因为这是我用MS Access运行的唯一一个,因为它没有在新版本中找到JetDriver。

我已将映射文件,类和代码放在屏幕截图中出现错误,因为我无法弄清楚如何在此处发布XML代码...它一直将其作为html标签读取并跳过一半。反正。

映射:
http://www.nickthissen.nl/Images/tmp7B5A.png

班级:
http://www.nickthissen.nl/Images/tmpF809.png

发生错误的加载代码:
http://www.nickthissen.nl/Images/tmp46B6.png
(正如我所说,内部异常说“发现了模糊的匹配”。

(我的示例中的产品已被Person替换)

Person和Category类继承Entity,它是一个抽象基类,并定义Id,Deleted,CreatedTime和UpdatedTime属性。 发生错误的代码位于通用的“manager”类中(类型参数TEntity必须继承实体)。它应该只是加载Deleted属性为false的所有实体。在这种情况下,TEntity是'Person'。

如果我在Person映射中省略了多对一的Category映射,它可以正常工作,但显然Category属性总是为null。

哦,是的,抱歉C#和VB之间的混合,C#代码在我用于多个项目的通用框架中,而VB部分是我网站上该框架的实际实现,我恰好使用VB这一点。

帮助?谢谢!

2 个答案:

答案 0 :(得分:0)

在您的Product类中,只需要包含Category对象,您不需要CategoryId属性。然后在您的产品映射中,您需要输入此条目

<many-to-one name="Category" column="CategoryId" />

<强>更新: 您的映射似乎缺少标记中映射类的完全限定名称。见http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-class

更新2

看看这是否对您有所帮助NHibernate 1.2 in a .NET 4.0 solution

答案 1 :(得分:0)

发现'模糊匹配'异常是由针对.NET Framework 4的项目引起的,该框架似乎与NHibernate 1.2.1不兼容。我切换到3.5,这似乎解决了这个特定的问题。

现在开始下一个。如您所见,Person类具有CategoryName属性,该属性应返回当前Category对象的名称,如果类别恰好为null,则返回空字符串。这样我就可以将Person对象的集合数据绑定到网格,将“CategoryName”指定为将列绑定到的属性。

显然这不适用于NHibernate。每当我尝试数据集我的人员时,我都会遇到这个例外:

"Property accessor 'CategoryName' on object 'NHibernateWebTest.Database.Person' threw the following exception:'Could not initialize proxy - the owning Session was closed.'"

在此代码中的'DataBind'方法调用中会发生这种情况:

        public virtual void LoadGrid()
        {
            if (this.Grid == null) return;

        this.Grid.DataSource = this.Manager.Load();
        this.Grid.DataBind();
    }

(这是一个ASP.NET项目,'Grid'是一个GridView)

'this.Manager'返回一个现有的NHibernateEntityManager实例,我之前已经显示过它的Load方法,它包含了这个:

        this.Grid.DataSource = this.Manager.Load();
        this.Grid.DataBind();
    }

(这里有一些通用的类型参数,但是这个网站似乎隐藏了它们(由于html喜欢的标签,我猜)...抱歉)。

这可能与NHibernate本身有关,正如我所说,我对此完全陌生。当我调用我的Load方法时,我希望它返回一个EntityCollection(Of Person),其中已经设置了所有属性。在我出于某种原因进行数据绑定时,似乎我必须保持ISession打开..?这看起来有点奇怪...... 我可以解决这个问题吗?我可以让我的Load方法只返回已经完全加载的人的集合,这样我可以随时访问CategoryName吗?

等等......这可能是懒惰加载吗?