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