4

我有以下数据结构:

+---------+
|Resume   |
+---------+
|Id (PK)  |
|IsActive |
|...      |
|..       |
|.        |
+---------+

+--------------------+
|Resume_Translation  |
+--------------------+
|ResumeId (PK, FK)   |
|Language (PK)       |
|Title               |
|Description         |
|...                 |
|..                  |
|.                   |
+--------------------+

所以我可以用两个连接的表来获得这样的数据:

+----------------------------------------------------------+
|Id | IsActive | ResumeId | Language | Title | Description |
+----------------------------------------------------------+
|1  | true     | 1        | 'fr'     | 'One' | 'One desc'  |
|1  | true     | 1        | 'pl'     | 'Raz' | 'Raz Opis'  |
|2  | true     | 2        | 'fr'     | 'B'   | 'bla bla'   |
|3  | true     | 3        | 'fr'     | 'C'   | 'C bla bla' |
+----------------------------------------------------------+

从我的领域的角度来看,我只关心Resume实体。我不想拥有Resume实体及其集合,Resume_Translations因为我只会拥有一个Resume具有当前翻译的实体。

public class Resume
{
    public virtual int Id{ get; protected internal set; }

    public virtual string Language { get; protected internal set; }

    public virtual string Title { get; protected internal set; }

    public virtual string Description { get; protected internal set; }

    public virtual bool IsActive { get; protected internal set; }
}

我当前与 Fluent NHibernate 的映射如下:

public class ResumeMap : ClassMap<Resume>
{

    public ResumeMap()
    {
        Table("Resume");
        Id(x => x.Id);
        Map(x => x.IsActive);
        // other properties
        Join("Resume_Translation", m =>
                        {
                            m.Fetch.Join();
                            m.Map(x => x.Language).Length(5);
                            m.Map(x => x.Title).Length(100);
                            m.Map(x => x.Description).Length(200);
                        });
    }
}

我可以毫无问题地从存储库中获取我想要的内容,只需传入 WHERE 谓词、简历的 ID 和我想要的语言。

但是我在插入和更新值时遇到了一些问题。

我的问题是:如何定义 NHibernate 仅在 Resume_Translation 表中插入新记录而不是更新当前实体的记录的映射?

所以我想要实现的是如果我在数据库中有以下记录:

|2  | true     | 2        | 'fr'     | 'B'   | 'bla bla'   |

加入有利于表之间的一对一关系,所以如果我将它放入我的实体并更改语言和翻译,nhibernate 正在执行更新,我可以理解它。如果我尝试通过不同的语言和翻译添加具有相同 ID 的新实体,nhibernate 会产生一个错误,即密钥已经存在并且我也理解它。

所以,我当然走错了路,但如果有人能指出我如何实现我想要的映射的正确解决方案,我将不胜感激。

另一个问题,您如何从业务角度处理实体及其翻译?

在此先感谢您的帮助。

托马斯

4

3 回答 3

2

斯特凡走在正确的轨道上。我已经调整了他的建议,使其具有双向关联,这将使更新变得更加容易。这种方法的一个问题是您需要在插入时手动分配 ResumeTranslation 实例的 Resume 属性,以便 NHibernate 将正确地将 Resume 表键分配给 ResumeTranslation 行。因此,鉴于您正在映射的关联,这就是它在 Fluent NH 中的外观:

public class ResumeTranslation
{
    public virtual string Title { get; protected internal set; }

    public virtual string Description { get; protected internal set; }

             //Needed for bi-directional association:
    public virtual Resume Resume { get; set; }
}


public class ResumeTranslationMap : ClassMap<ResumeTranslation>
{

    public ResumeTranslationMap()
    {
        Table("ResumeTranslation");
        CompositeId()
            .KeyReference(kp => kp.Resume, "ResumeId")
            .KeyProperty(kp => kp.Language, "Language");

        Map(x => x.Title);
        Map(x => x.Description);
    }
}

public class ResumeMap : ClassMap<Resume>
{

    public ResumeMap()
    {
        Table("Resume");
        Id(x => x.Id);
        Map(x => x.IsActive);
        // other properties

        HasMany(c => c.Translations)
            .Inverse()
            .KeyColumn("id") //May not be required but here for reference
            .Cascade.All();
    }
}
于 2011-07-12T15:42:05.023 回答
2

使用字典,使用语言作为键呢?

public class ResumeTranslation
{
    public virtual string Title { get; protected internal set; }

    public virtual string Description { get; protected internal set; }
}

public class Resume
{
    public virtual int Id{ get; protected internal set; }

    // language is the key to the translation
    // you may even want to hide the dictionary from the public interface of
    // this class and only provide access to a "current" language.
    public virtual IDictionary<string, ResumeTranslation> Translations { get; private set; }

    public virtual bool IsActive { get; protected internal set; }
}

并相应地将其映射为 amap与复合元素(对不起,我没有使用流利的,所以不要问我它会是什么样子)。它将与您的数据库模型完全匹配。

于 2011-07-12T15:18:18.003 回答
2

对我来说似乎是一对多的关系。我个人会在我的Resume对象中收集ResumeTranslation对象。然后,我会将其映射为标准的一对多。

然后,您可以将另一个属性ActiveResumeTranslation添加到您的Resume实体中,该实体代表您的current translation.

于 2011-07-12T13:25:41.233 回答