【问题标题】:How to reference a class with 2 cols CompositeId from a class with 2 cols CompositeId in FluentNhibernate?如何从 FluentNhibernate 中具有 2 列 CompositeId 的类中引用具有 2 列 CompositeId 的类?
【发布时间】:2012-02-13 16:29:51
【问题描述】:

我正在尝试创建一个

public class BaseMap<T> : ClassMap<T>

我的应用程序。它应该支持本地化实体,它们的主键必须是 Id 和 Language:

CompositeId()
    .KeyProperty(x => x.Id)
    .KeyProperty(x => ((ILocalizedEntity)x).Language);

我想要的另一件事是一个本地化类能够引用另一个本地化类。

我做了以下(经过大量研究,这就是我所拥有的):

    public new ManyToOnePart<TOther> References<TOther>(Expression<Func<T, TOther>> memberExpression) where TOther : BaseEntity
    {
        if (typeof(ILocalizedEntity).IsAssignableFrom(typeof(TOther)))
        {
            return base.References(memberExpression)
                .Columns("CategoryId")
                .Columns("Language");
        }

        return base.References(memberExpression);
    }

这在尝试插入时给了我 IndexOutOfRange 异常,原因是“语言”属性被映射了两次,但数据库中只有 1 个语言列,所以我这样做了:

    public new ManyToOnePart<TOther> References<TOther>(Expression<Func<T, TOther>> memberExpression) where TOther : BaseEntity
    {
        if (typeof(ILocalizedEntity).IsAssignableFrom(typeof(TOther)))
        {
            return base.References(memberExpression)
                .Columns("CategoryId")
                .Columns("Language")
                .Not.Update()
                .Not.Insert();
        }

        return base.References(memberExpression);
    }

解决了 IndexOutOfRange 问题,但没有完成我想要的。因为它总是在“CategoryId”列中插入NULL,因为我指定了Not.Insert()和Not.Update(),所以它没有!

现在,我希望它映射“CategoryId”而不是“Language”,因为它已经映射,因为它是 ComposideId(主键)的一部分。

所以我试了一下:

    public new ManyToOnePart<TOther> References<TOther>(Expression<Func<T, TOther>> memberExpression) where TOther : BaseEntity
    {
        if (typeof(ILocalizedEntity).IsAssignableFrom(typeof(TOther)))
        {
            return base.References(memberExpression)
                .Columns("CategoryId")
                .Nullable()
                .Columns("Language")
                .Not.Update()
                .Not.Insert();
        }

        return base.References(memberExpression);
    }

希望它不会只插入或更新“Language”而不是“CategoryId”——但也没有运气。

我也尝试过在PK中先做语言:

            CompositeId()
                .KeyProperty(x => ((ILocalizedEntity)x).Language)
                .KeyProperty(x => x.Id);

并将引用更改为:

            return base.References(memberExpression)
                .Columns("Language")
                .Not.Update()
                .Not.Insert()
                .Columns("CategoryId")
                .Nullable();

但“Not.Insert()”和“Not.Update()”仍然影响“Language”和“CategoryId”。

我尝试在“References”调用之前映射“CategoryId”,如下所示:

            Map(memberExpression, "Language");
            return base.References(memberExpression)
            .......

但它失败了。

任何人都有任何想法,当主键和外键中的 1 列共用时,如何从具有 2 列 CompositeId 的类中引用具有 2 列 CompositeId 的类?

【问题讨论】:

  • 尽可能避免使用compositeIds。以下也避免了重复stackoverflow.com/a/5431842/671619
  • 不过,如果我想使用它们,为什么要这么复杂呢?如果您认为程序和数据库中的架构是正确的,那么复合 id 有时是最好的选择……不是吗?

标签: c# fluent-nhibernate foreign-keys composite-key fluent-nhibernate-mapping


【解决方案1】:

我有一个类似的问题,compositeid 的一部分是参考,我无法用谷歌解决它,所以我也无法自己尝试 2 周,因此不喜欢他们。

在某些情况下CompositeId 有它的位置,但在你所描述的情况下很可能不是。一个简单的字典和方便的属性来获取实际语言的值要简单得多,并且避免重复所有其他对每种语言都相同的属性。

【讨论】:

  • 真的所有语言都一样吗?我不知道......我试图完成的是将本地化逻辑应用于每个新实体......我只是希望它从接口继承并让魔法完成......如果不是为了那个小的技术约束..
  • 一些缺点:1)当你通过 id 查询时,你总是需要知道语言 2)你总是必须在每个查询中添加语言 3)你必须自己管理 id(不能将现有的 idgenerators 与 CompositeId 一起使用)4)Category.Color、Category.Type 等将为每种语言重复
  • 5) 在程序中切换语言时,您必须重新加载实体 6) 如果缺少本地化实体,则实施回退意味着您必须再次查询数据库以获取默认语言实体,而不是使用默认语言实体在字典里
猜你喜欢
  • 1970-01-01
  • 2015-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多