【问题标题】:Mapping tree structure with Fluent NHibernate使用 Fluent NHibernate 映射树结构
【发布时间】:2012-12-07 15:42:20
【问题描述】:

我在使用 Fluent NHibernate 映射树结构时遇到了麻烦,而我也不必添加我认为是 hack 的东西。

考虑以下类:

  • Node(抽象,有int IdGroupNode Parent(如果null,则节点驻留在根节点中))
  • GroupNode(继承自Node,具有IList<GroupNode> GroupsIList<ItemNode> Items
  • ItemNode(继承自 Item

理想情况下,这将具有以下数据库结构:

  • GroupNodes(整数 ID,可为空的整数 ParentId)
  • ItemNodes(整数 Id,可为空的整数 ParentId)

我的映射器如下所示:

public class GroupNodeMap : ClassMap<GroupNode>
{
    public GroupNode()
    {
        Id(x => x.Id);
        References(x => x.Parent);
        HasMany(x => x.Groups).LazyLoad();
        HasMany(x => x.Items).LazyLoad();
    }
}

public class ItemNodeMap : ClassMap<ItemNode>
{
    public ItemNodeMap()
    {
        Id(x => x.Id);
        References(x => x.Parent);
    }
}

不幸的是,这会创建一组重复的引用(每个表都有一个ParentId 和一个GroupNodeId。我可以通过在.LazyLoad() 之后添加.KeyColumn("ParentId") 来调整这种行为,但这感觉就像一个黑客,我希望它使用约定或 lambdas 而不是魔术字符串来表达。

谁能指出我正确的方向?

【问题讨论】:

  • 我也有同样的问题...
  • 你找到解决办法了吗?

标签: c# nhibernate fluent-nhibernate nhibernate-mapping


【解决方案1】:

这是一个示例,您可以尝试使用 AutoMap 约定和SQLite

namespace Entities
{
    public abstract class Node
    {
        public virtual int Id { get; set; }
        public virtual GroupNode Parent { get; set; }
    }

    public class ItemNode : Node
    {
    }

    public class GroupNode : Node
    {
        public virtual IList<GroupNode> Groups { get; set; }
        public virtual IList<ItemNode> Items { get; set; }
    }
}

class Program
{
    static void Main()
    {
        if (File.Exists("data.db3"))
        {
            File.Delete("data.db3");
        }

        using (var factory = CreateSessionFactory())
        {
            using (var connection = factory.OpenSession().Connection)
            {
                ExecuteQuery("create table GroupNode(Id integer primary key, Parent_Id integer)", connection);
                ExecuteQuery("create table ItemNode(Id integer primary key, Parent_Id integer)", connection);

                ExecuteQuery("insert into GroupNode(Id, Parent_Id) values (1, null)", connection);
                ExecuteQuery("insert into GroupNode(Id, Parent_Id) values (2, 1)", connection);
                ExecuteQuery("insert into GroupNode(Id, Parent_Id) values (3, 1)", connection);

                ExecuteQuery("insert into ItemNode(Id, Parent_Id) values (1, 1)", connection);
                ExecuteQuery("insert into ItemNode(Id, Parent_Id) values (2, 1)", connection);
            }

            using (var session = factory.OpenSession())
            using (var tx = session.BeginTransaction())
            {
                var node = session.Get<GroupNode>(1);
                tx.Commit();
            }
        }
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(
                SQLiteConfiguration.Standard.UsingFile("data.db3").ShowSql()
            )
            .Mappings(
                m => m.AutoMappings.Add(
                    AutoMap
                        .AssemblyOf<Program>()
                        .Where(t => t.Namespace == "Entities")
                )
            ).BuildSessionFactory();
    }

    static void ExecuteQuery(string sql, IDbConnection connection)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = sql;
            command.ExecuteNonQuery();
        }
    }
}

【讨论】:

    【解决方案2】:

    我的数据库中有完全相同类型的结构,我也使用了 KeyColumn 方法。这并不是真正的 hack,它只是解释 fluentnhibernate 集合的另一端的名称是什么。

    这是一种特殊情况,因为通常如果您设置“HasMany(x => x.Groups)”,他将在表 Group 中搜索“GroupId”。但在您的情况下, GroupId 已经是该列的键,它不是您要用于此的列。这就是为什么你必须设置“KeyColumn”来告诉 fnh 他应该使用哪一列来建立关系。

    KeyColumn 方法经常使用,尤其是在处理尚未为 NHibernate 构建的数据库并且列具有奇怪名称时。

    【讨论】:

      【解决方案3】:

      Fluent NHibernate 有命名约定。 如果您不喜欢使用数据库列名(这不是 hack),您应该重命名数据库列。 检查Available Conventions

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-18
        • 2010-12-09
        • 2012-04-03
        • 1970-01-01
        相关资源
        最近更新 更多