【问题标题】:Simple relation between two tables两个表之间的简单关系
【发布时间】:2011-06-08 01:44:58
【问题描述】:

我今天开始使用 NHibernate,但我不知道如何在两个表之间建立简单的关系。我真的不知道它叫什么,它可能是一对多或外键关系(我不喜欢数据库设计和使用的术语),但这里有一个非常简单的例子。

我有一个带有属性 ID (PK)、ProductName 和 CategoryId 的表 Product。然后我有一个带有属性 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 属性?

似乎我需要一个“一对多”关系,因为我每个产品都有一个类别(或者这个推理是否倒退?)但似乎没有一对多映射......

感谢您的帮助!

加法:

我尝试在 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 和 Category 类继承了 Entity,它是一个抽象基类,定义了 Id、Deleted、CreatedTime 和 UpdatedTime 属性。 发生错误的代码位于通用“管理器”类中(类型参数 TEntity 必须继承实体)。它只是应该加载所有具有已删除属性为假的实体。在这种情况下,TEntity 是“Person”。

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

哦,是的,很抱歉 C# 和 VB 之间的混合,C# 代码位于我用于多个项目的通用框架中,而 VB 部分是该框架在我的网站上的实际实现,我只是碰巧使用 VB那个。

帮助?谢谢!

【问题讨论】:

    标签: nhibernate mapping key one-to-many


    【解决方案1】:

    在你的 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

    【讨论】:

    • 我试过这个,但我一直收到一个异常说“创建代理失败”,并且在内部异常中“找到了不明确的匹配”。我想向您展示它发生的代码和映射,但似乎我无法在评论中做任何事情(我是这个网站的新手)......我应该如何向您展示我尝试过的内容我无法显示任何代码/xml 映射?
    • 我在顶部的问题中添加了所有内容,请参见此处。
    • 似乎没有什么不同。我将 name="Person" 替换为 name="NhibernateWebTest.Database.Person" (类别相同),但行为保持不变。我可以查看和编辑类别,但我无法查看这些人,因为它在尝试加载他们时给了我同样的错误。
    • @Nick Thissen,您的实体似乎位于不同的程序集中(我假设是这样,因为您在实体中使用 VB,但在加载器类中使用 C#)。这意味着您还需要提供程序集名称,例如 name="NhibernateWebTest.Database.Person, NhibernateWebTest" 或任何实际的程序集
    • 仍然不行 :( 让我解释一下项目设置。我有一个项目 DatabaseFramework (C#),其中包含 Entity 基类和 EntityManager 类(它具有 Load 方法)抛出异常)。然后,我有另一个项目,NHibernateWebTest (VB),其中包含 Person 和 Category 类(从另一个项目继承 DatabaseFramework.Entity),并包含映射文件。让我重复一遍:映射文件和实体类在 NHibernateWebTest 项目中,而实体基础和加载方法在另一个项目中。
    【解决方案2】:

    “发现不明确的匹配”异常是由面向 .NET Framework 4 的项目引起的,该项目似乎与 NHibernate 1.2.1 不兼容。我切换到 3.5,这似乎解决了这个特定问题。

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

    显然这不适用于 NHibernate。每当我尝试对我的人员集合进行数据绑定时,都会出现以下异常:

    “对象 'NHibernateWebTest.Database.Person' 上的属性访问器 'CategoryName' 引发以下异常:'无法初始化代理 - 拥有的 Session 已关闭。'”

    这发生在此代码中的“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 方法,它包含以下内容:

            public virtual EntityCollection Load()
            {
                using (ISession session = this.GetSession())
                {
                    var entities = session
                                    .CreateCriteria(typeof (TEntity))
                                    .Add(Expression.Eq("Deleted", false))
                                    .List();
                    return new EntityCollection(entities);
                }
            }
    

    (那里有一些通用类型参数,但这个网站似乎隐藏了它们(由于我猜想像 html 这样的标签)......对此感到抱歉)。

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

    等等...这可能是延迟加载吗?

    【讨论】:

    • 开始一个新问题,我会为您发布解决方案,也请随时将我的答案标记为已接受;)
    • 好的,我会的。我还没有将其标记为已接受,因为...它尚未解决:p 我无法验证您的解决方案(多对一解决方案)是否符合我的要求,但您似乎相当有信心,所以好的:)
    • 我开始了一个新问题,请看这里:stackoverflow.com/questions/4685671/…
    猜你喜欢
    • 2022-09-29
    • 1970-01-01
    • 2016-06-27
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 2020-09-14
    • 1970-01-01
    相关资源
    最近更新 更多