Fluent NHibernate 多对一映射问题

发布于 2024-12-03 21:14:56 字数 2138 浏览 1 评论 0原文

编辑

我有答案并将于明天发布。

我有一个类似乎使用父主键列而不是它自己的主键列。

这里涉及到两个类ActionHistory和ActionData。父类 ActionHistory 表示一个操作以及执行该操作的详细信息。子类 ActionData 表示由操作创建的一段数据。每个 ActionHistroy 都有许多 ActionData,这通过多对一映射来表示。

这些类是:

public class ActionHistory
{
    public virtual int Code { get; set; } 
    public virtual string Doneby { get; set; }
    public virtual IList<ActionData> _ActionData{ get; set;}
}

public class ActionData
{
    public virtual int Code { get; set; }
    public virtual double Data{ get; set; }
    public virtual ActionHistory _ActionHistory{ get; set; }
}

我的映射是:

public class ActionHistoryClassMap : ClassMap<ActionHistory>
{
    public ActionHistoryClassMap ()
    {
        Table("ACTIONHISTORY");
        Id(x => x.Code, "CODE").GeneratedBy.Assigned();
        Map(x => x.Doneby, "DONEBY");
        HasMany(x => x._Actiondata).KeyColumn("CODE").AsBag().Cascade.All();
    }
}

public class ActionDataClassMap : ClassMap<ActionData>
{
    public ActionDataClassMap ()
    {
        Table("ACTIONDATA");
        Id(x => x.Code, "CODE").GeneratedBy.Assigned();
        Map(x => x.Data, "DATA");
        References(x => x._ActionHistory, "ACTIONHISTORYID");
    }
}

问题是当查询 ActionHistory 类时,会返回正确的 ActionHistory,但它包含的 HistoryData 是错误的。应该返回一个 HistoryData 列表,但只返回一个 HistoryData,并且它的 Code 值是父 ActionHistory 类的 Code 值。我相信我的问题源于这样一个事实:两个类具有相同的主键列名称,而我没有正确处理这个问题。相关的列是 ACTIONHISTORY 表中的 CODE 和 ACTIONDATA 表中的 ACTIONHISTORYID。数据库是固定的,所以我无法重命名任何列。在这种情况下,数据仅从数据库中读取,而不保存或更新。

我下载了 NHibernate Profiler 来帮助我解决这个问题,并找到了 SQL 中出现问题的确切位置。

这是生成的用于返回 ActionData 的 SQL 查询(其中 18 是 ActionHistory 主键):

SELECT actiondat0_.CODE              as CODE1_,
   actiondat0_.CODE              as CODE9_0_,
   actiondat0_.DATA              as DATA9_0_,
   actiondat0_.ACTIONHISTORYID  as ACTIONHI4_9_0_
FROM   ACTIONDATA actiondat0_
WHERE  actiondat0_.CODE = 18 /* @p0 */

最后一行应该是:

WHERE  actiondat0_.ACTIONHISTORYID = 18 /* @p0 */

但我只是不明白为什么映射没有生成正确的查询。

Edit

I have the answer and will post it up tomorrow.

I have a class that appears to be using the parent primary key column instead of it's own primary key column.

There are two classes involved here ActionHistory and ActionData. The parent class, ActionHistory, represents an action and details who performed the action. The child class, ActionData, represents a piece of data that was created by the action. Each ActionHistroy has a number of ActionData and this is represented through a many to one mapping.

The classes are:

public class ActionHistory
{
    public virtual int Code { get; set; } 
    public virtual string Doneby { get; set; }
    public virtual IList<ActionData> _ActionData{ get; set;}
}

public class ActionData
{
    public virtual int Code { get; set; }
    public virtual double Data{ get; set; }
    public virtual ActionHistory _ActionHistory{ get; set; }
}

My mappings are:

public class ActionHistoryClassMap : ClassMap<ActionHistory>
{
    public ActionHistoryClassMap ()
    {
        Table("ACTIONHISTORY");
        Id(x => x.Code, "CODE").GeneratedBy.Assigned();
        Map(x => x.Doneby, "DONEBY");
        HasMany(x => x._Actiondata).KeyColumn("CODE").AsBag().Cascade.All();
    }
}

public class ActionDataClassMap : ClassMap<ActionData>
{
    public ActionDataClassMap ()
    {
        Table("ACTIONDATA");
        Id(x => x.Code, "CODE").GeneratedBy.Assigned();
        Map(x => x.Data, "DATA");
        References(x => x._ActionHistory, "ACTIONHISTORYID");
    }
}

The problem is when an ActionHistory class is queried the correct ActionHistory is returned but the HistoryData that it contains is wrong. A list of HistoryData should be returned but only one HistoryData is returned and it's Code value is the Code values of the parent ActionHistory class. I believe my problem stems form the fact that both classes have the same primary key column name and I'm not handling this properly. The columns that that are related are CODE from the ACTIONHISTORY table and ACTIONHISTORYID from the ACTIONDATA table. The database is fixed so I can't rename any columns. In this case data is only read from the database and not saved or updated.

I downloaded NHibernate Profiler to help me with this problem and have found the exact point in the SQL where the problem occurs.

This is the SQL query that is generated to return the ActionData (where 18 is the ActionHistory primary key):

SELECT actiondat0_.CODE              as CODE1_,
   actiondat0_.CODE              as CODE9_0_,
   actiondat0_.DATA              as DATA9_0_,
   actiondat0_.ACTIONHISTORYID  as ACTIONHI4_9_0_
FROM   ACTIONDATA actiondat0_
WHERE  actiondat0_.CODE = 18 /* @p0 */

The last line should be:

WHERE  actiondat0_.ACTIONHISTORYID = 18 /* @p0 */

But I just do not understand why the mapping is not generating the right query.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

七堇年 2024-12-10 21:14:56

我知道这是一件显而易见的事情,经过几个小时的毫无进展后,它当然突然出现在我身上。

ActionHistory 类映射当然应该是:

public class ActionHistoryClassMap : ClassMap<ActionHistory>
{
    public ActionHistoryClassMap ()
    {
        Table("ACTIONHISTORY");
        Id(x => x.Code, "CODE").GeneratedBy.Assigned();
        Map(x => x.Doneby, "DONEBY");
        HasMany(x => x._Actiondata).KeyColumn("ACTIONHISTORYID")
            .AsBag().Cascade.All();
    }
}

区别在于 KeyColumn 方法现在是 ACTIONHISTORYID,而不是 CODE。我没有意识到 KeyColumn 应该引用 ActionHistory 键列。现在看来很明显,而且我在这个项目中实现它的所有其他时间都没有帮助,具有关系的列始终具有相同的名称。

I know it was something blindingly obvious and after hours of getting nowhere it of course jumps out at me.

The ActionHistory class map should of course be:

public class ActionHistoryClassMap : ClassMap<ActionHistory>
{
    public ActionHistoryClassMap ()
    {
        Table("ACTIONHISTORY");
        Id(x => x.Code, "CODE").GeneratedBy.Assigned();
        Map(x => x.Doneby, "DONEBY");
        HasMany(x => x._Actiondata).KeyColumn("ACTIONHISTORYID")
            .AsBag().Cascade.All();
    }
}

The difference being the KeyColumn method is now ACTIONHISTORYID as opposed to CODE. I didn't cop that KeyColumn should reference the ActionHistory key column. It seems obvious now and it didn't help that all other times I implemented it in this project the columns with the relationship always had the same name.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文