【问题标题】:How to map a related table with no primary key with fluent-NHibernate如何使用fluent-NHibernate映射没有主键的相关表
【发布时间】:2012-06-05 12:15:42
【问题描述】:

在我看来很常见:我有两张桌子: 文件: dID (pk, int), dName(varchar)

和文档选项: dID (int), oType(int), oValue(varchar)

我想要一个带有属性选项的文档类(DocumentOption 类的列表)

由于 document_options 没有 PK,我不能使用 HasMany,而且该表中的行看起来也不是“真实”实体...

我看到了一种为文档选项生成自动编号键并使用 HasMany 进行映射的方法,或者可能创建一个复合 ID,但我想知道是否有更好的选项我不知道。

【问题讨论】:

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


    【解决方案1】:

    在这种情况下,DocumentOptions 是一个值对象,因为它没有自己的身份,并且在它所属的文档之外没有任何意义。因此,您可以使用Component 将集合属性映射到值对象。

    public class Document : Entity // don't worry about Entity; it's a base type I created that contains the Id property
    {
        public virtual string Name { get; set; }
    
        public virtual IList<DocumentOptions> Options { get; protected set; }
    
        public Document()
        {
            Options = new List<DocumentOptions>();
        }
    }
    
    public class DocumentOptions
    {
        public virtual int Type { get; set; }
    
        public virtual string Value { get; set; }
    }
    

    还有映射:

    public DocumentMap()
    {
        Table("documents");
    
        Id(c => c.Id)
            .Column("dId")
            .GeneratedBy.HiLo("10");
    
        Map(c => c.Name)
            .Column("dName");
    
        HasMany(c => c.Options)
            .Component(c =>
                           {
                               c.Map(c2 => c2.Value).Column("oValue");
                               c.Map(c2 => c2.Type).Column("oType");
                           })
            .Table("document_options")
            .KeyColumn("dId")
            .Cascade.AllDeleteOrphan();
    
    }
    

    【讨论】:

    • 谢谢,经过大量阅读,我想出了一个非常相似的答案,只是它没有使用 Id,也许还有其他一些琐事 =)
    • 确实有几个类似的方法。除了忘记指定表名外,我试图让映射与您在问题中指定的表完全匹配。
    • 你介意告诉我为什么你使用“受保护的集合”并在构造函数中创建一个新的选项列表吗?我的解决方案似乎有效,但您似乎比我更了解它。
    • 您不必这样做,但我这样做是为了防止我的 API 的消费者在他们忘记在使用之前初始化集合的情况下获得NullReferenceException。此外,我向这些消费者表明,Options 是由 API 管理的,而不是由他们使用 protected set 管理的;他们只需要担心添加、删除和/或枚举选项(如果有的话)。同样,这不是必需的,但对我来说是一种好的习惯。
    【解决方案2】:

    如果我理解正确,我必须将选项映射为组件列表:

    HasMany(x => x.DocumentOptions)
        .Table("document_options")
        .KeyColumn("dID")
        .Component(c => {
                c.Map(x => x.Option, "oID");
                c.Map(x => x.Value, "oValue");
        })
        .Fetch.Subselect(); //This type of join isn't strictly needed, is used for SQL optimization
    

    类仅供参考:

    public class Options {
        public virtual int Option { get; set; }
        public virtual int Value { get; set; }
    }
    
    public class Document {
        public virtual int ID { get; set; }
        public virtual String Name { get; set; }
        public virtual IList<DocumentOption> DocumentOptions { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-20
      • 1970-01-01
      • 2011-03-02
      • 2014-05-26
      • 2011-08-31
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多