具有多个值的 NHibernate 三元关联 - 如何以一种很好的方式映射

标签 nhibernate orm associations ternary fluent-nhibernate-mapping

我问过一个类似的问题,但我已经放弃了我在那里解决这个问题的想法,所以我想要一些帮助以一种巧妙的方式解决这个问题。

我有 table

Image - (Id, Name, RelativeFilePath)
ImageFilter - (Id, Type)
ImageContext - (Id, Name, ...)
ImageContextImage - (Id, ImageContextId, ImageId, ImageFilterId)

数据示例:
ImageContextImage      Id        ImageContextId         ImageId        ImageFilterId
                       1         1                      1              1
                       2         1                      1              2
                       3         2                      1              1
                       4         3                      2              1

如您所见,上下文中的图像可以应用多个过滤器。

我所有的实体都非常简单,除了上面的这个映射。目前我有
ImageContext
    public virtual int Id
    public virtual string Name
    public virtual IList<ImageContextImage> Images

ImageContextImage
    public virtual int Id
    public virtual ImageContext Context
    public virtual Image Image
    public virtual ImageFilter ImageFilter

上面很容易映射,但是对于每个图像,我会得到多个 ImageContextImage 对象。我宁愿让 ImageContextImage 包含一个 ImageFilter 列表,这样我就可以简单地遍历该集合。我已经尝试了很多 AsTernaryAssociation() 的排列,它提示我需要一个字典,但我想要每个键有多个值!有任何想法吗?

有任何想法吗?谢谢!

最佳答案

三元关联可以替换为二元关联,但替换后会出现一个新实体 ( Removing Ternary relationship types )。在您的情况下是 ImageContextImage 实体,困难的部分是为此类实体找到最佳名称。你的例子非常接近这个替代品。

ImageContextImage 实体:

public virtual int Id { get; set; }
public virtual Image Image { get; set; }
public virtual ImageContext Context { get; set; }
public virtual IList<ImageFilter> Filters { get; set; }

它的映射:
Id(x => x.Id);
References(x => x.Image);
References(x => x.Context);
HasManyToMany(x => x.Filters); // filters are referenced via many-to-many relation

ImageContext 实体:
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<ImageContextImage> ImageContextImageList { get; set; }

它的映射:
Id(x => x.Id);
Map(x => x.Name);
HasMany(x => x.ImageContextImageList)
    .Inverse(); // to aggregate all ImageContextImage that are fererencing this instnstance of ImageContext
    .KeyColumn("Context_id");

对应的数据库架构略有不同:
ImageContextImage(Id, Image_id, Context_id)

并且必须为多对多关系创建新的关联表:
ImageFilterToImageContextImage(ImageContextImage_id, ImageFilter_id)

请注意,这只是一种可能方法的草图。许多细节取决于您的问题域,并且必须在它准备好用于生产之前进行调整:) - 例如级联。

我从未使用过 AsTernaryAssociation 但它看起来很有趣。稍后我会研究它,谢谢你的启发:)。

编辑:
三元关联可以通过稍微不同的映射(使用复合元素)来实现,但仍然有额外的实体 - ImageContextImage 在这种情况下被映射为组件:
public class ImageContext
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<ImageContextImage> ImageContextImageList { get; set; }

    public ImageContext()
    {
        ImageContextImageList = new List<ImageContextImage>();
    }
}

public class ImageContextMap : ClassMap<ImageContext>
{
    public ImageContextMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        HasMany(x => x.ImageContextImageList).Component(c =>
        {
            c.References(x => x.Image);
            c.References(x => x.Filter);
        }).Cascade.AllDeleteOrphan();
    }
}

public class ImageContextImage
{
    public virtual Image Image { get; set; }
    public virtual ImageFilter Filter { get; set; }
}

ImageContext 类可以通过这些方法进行扩展,使事情变得更简单:
public virtual IEnumerable<Image> AssociatedImages
{
    get
    {
        return ImageContextImageList.Select(x => x.Image).Distinct().ToList();
    }
}

public virtual IEnumerable<ImageFilter> GetFilters(Image image)
{
    return ImageContextImageList.Where(x => x.Image == image).Select(x => x.Filter).ToList();
}

AsTernaryAssociation 没有成功。

关于具有多个值的 NHibernate 三元关联 - 如何以一种很好的方式映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5985253/

相关文章:

c# - 如何使用 "not in"执行 NHibernate QueryOver?

php - Laravel 多对多自引用表只能以一种方式工作

ruby-on-rails - ruby on Rails 上的构建方法

ruby-on-rails - 我如何用 :has_one assocation :through a collection, 表达 :condition to construct/select "the one"?

如果之前违反了唯一约束,NHibernate 将停止

c# - 列表中的列表(模型)工厂

java - Jpa 删除具有替代多对一关系的可选父级

javascript - Sequelize hasOne 关联限制

c# - NHibernate QueryOver 用投影填充父对象中的属性对象

go - 无法将类型字符串用作 sql.NullString