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

NHibernate具有多个值的三元关联-如何以良好的方式映射,nhibernate,orm,associations,ternary,fluent-nhibernate-mapping,Nhibernate,Orm,Associations,Ternary,Fluent Nhibernate Mapping,我问过一个类似的问题,但我已经放弃了解决这个问题的想法,所以我希望能得到一些帮助,以简洁的方式解决这个问题 我有桌子 Image - (Id, Name, RelativeFilePath) ImageFilter - (Id, Type) ImageContext - (Id, Name, ...) ImageContextImage - (Id, ImageContextId, ImageId, ImageFilterId) 数据示例: ImageContextImage Id

我问过一个类似的问题,但我已经放弃了解决这个问题的想法,所以我希望能得到一些帮助,以简洁的方式解决这个问题

我有桌子

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
ImageContext
公共虚拟整数Id
公共虚拟字符串名
公共虚拟IList映像
ImageContextImage
公共虚拟整数Id
公共虚拟图像上下文
公共虚拟映像
公共虚拟映像过滤器映像过滤器
上面的内容很容易映射,但是对于每个图像,我会得到多个ImageContextImage对象。我希望ImageContextImage包含ImageFilter的列表,这样我就可以简单地遍历该集合。我尝试了很多AsternaryAsociation()的排列,它抱怨我需要一个字典,但我希望每个键有多个值!有什么想法吗


有什么想法吗?谢谢

三元关联可以替换为二元关联,但替换后会出现一个新实体()。在您的案例中是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; }
ImageContext实体:

public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<ImageContextImage> ImageContextImageList { get; set; }
相应的数据库架构略有不同:

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
{
公共虚拟整数Id{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟IList ImageContextImageList{get;set;}
公共图像上下文()
{
ImageContextImageList=新列表();
}
}
公共类ImageContextMap:ClassMap
{
公共ImageContextMap()
{
Id(x=>x.Id);
Map(x=>x.Name);
HasMany(x=>x.ImageContextImageList)。组件(c=>
{
c、 参考文献(x=>x.Image);
c、 参考(x=>x.Filter);
}).Cascade.AllDeleteOrphan();
}
}
公共类ImageContextImage
{
公共虚拟映像映像{get;set;}
公共虚拟映像筛选器筛选器{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();
}
公共虚拟IEnumerable关联映像
{
得到
{
返回ImageContextImageList.Select(x=>x.Image).Distinct().ToList();
}
}
公共虚拟IEnumerable GetFilters(图像)
{
返回ImageContextImageList.Where(x=>x.Image==Image)。选择(x=>x.Filter.ToList();
}

AsTernaryAssociation没有成功。

您可以更改数据库模式(例如添加表、列等)吗?@Jakub嗯,在一定程度上。ImageFilter必须能够添加到多个图像和ImageContext中。那你有什么想法吗?:)嘿,谢谢!里面有很多有趣的东西。。。在我决定采取哪种方法之前,我需要仔细阅读它,但我认为我可以走上正确的道路。:)
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; }
}
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();
}