我应该如何将实体映射到两个表

时间:2013-02-19 13:55:46

标签: c# nhibernate fluent-nhibernate

请原谅这个尴尬的头衔。我不完全确定如何说出来

我有一个实体,我们称之为A。每周从电子表格中提取A,然后将其存储在表格中。电子表格是累积性的,因为6周前提取的数据包含在1周前的电子表格中。

现在,有时这些数据将是相同的,不需要更改。有时它需要改变。我想保持主表充满最新数据。也就是说,随着实体的更新,过时的实体将被删除,而较新的实体将被插入其位置。

A实体发生变化时,我创建了一个Conflict,这样Conflict就会有一个Guid,一个冲突发现的DateTime,一个评论和一个副本。旧实体(以便我们可以看到发生了什么变化等),以及相关的冲突。相关的冲突很好,但是我想知道如何坚持旧的实体。

我可以进行组件映射,但这只会爆炸表格,我相信我可以以更“漂亮”的方式做到这一点。

我的Conflict映射如下:

public class ConflictAMapping : ClassMap<Conflict<A>>
{
    public ConflictAMapping()
    {
        Id(c => c.Guid);
        Map(c => c.DateOfConflict);
        Map(c => c.Comment);
        HasMany(c => c.RelatedConflicts)
            .KeyColumn("ConflictKey")
            .Inverse()
            .Cascade.All()
            .Table("RelatedConflicts");
        References<A>(c => c.OriginalEntity)
            .Column("FK_IssueNumber")
            .Cascade.All();
    }
}

我的A映射

public class GSFEntityMapping : ClassMap<GSFEntity>
{
    public GSFEntityMapping()
    {

     ... unrelated properties blah blah ...
        HasMany(g => g.Conflicts).KeyColumn("theKey")
            .Table("Conflicts")
            .AsBag().Cascade.All()
    }
}

Conflict表如下所示:

Guid|DateOfConflict|CommentFK_IssueNumber|ConflictKey|theKey

A表中没有任何与冲突相关的内容(只是实际属性)。

那么如何映射旧实体呢?我是否必须为旧A实体生成一个新类,或者我可以通过某种方式在Fluent / NHibernate中执行此操作?

1 个答案:

答案 0 :(得分:0)

假设你有这样的课程

class Issue
{
    public virtual int Id { get; protected set; }
    public virtual string Key { get; set; }   // same for all versions of the issue
    public virtual DateTime Created { get; set; }
}

class Conflict<T>
{
    public virtual Guid Id { get; protected set; }
    public virtual T OriginalEntity { get; set; }
    public virtual DateTime DateOfConflict { get; set; }
    public virtual string Comment { get; set; }
    public virtual string IssueKey { get; set; }
    public virtual ICollection<Conflict<T>> RelatedConflicts { get; protected set; }
}

然后与

进行映射
  • 已删除Inverse,因为冲突中没有像RelatesTo
  • 那样的反向引用
  • Cascade.None()on Conflicts因为删除IssueVersion不应自动删除所有问题的冲突
  • 为了清晰起见重命名了一些列
  • 存档问题的第二个映射


public class ConflictAMapping : ClassMap<Conflict<Issue>>
{
    public ConflictAMapping()
    {
        Id(c => c.Id).GeneratedBy.Assigned();
        Map(c => c.DateOfConflict);
        Map(c => c.Comment);
        HasMany(c => c.RelatedConflicts)
            .KeyColumn("RelatedToConflict")
            .Cascade.All();
        References(c => c.OriginalEntity)
            .EntityName("ArchivedIssue")
            .Column("FK_Issue_id")
            .Cascade.All();
    }
}

public class IssueMapping : ClassMap<Issue>
{
    public IssueMapping()
    {
        Id(c => c.Id).GeneratedBy.Assigned();
        Map(c => c.Key);
        Map(c => c.Created);
        HasMany(g => g.Conflicts)
            .KeyColumn("IssueKey")
            .PropertyRef("Key")
            .Cascade.None();
    }
}

public class ArchivedIssueMapping : IssueMapping
{
    public ArchivedIssueMapping()
    {
        Table("ArchivedIssues");
        EntityName("ArchivedIssue");
    }
}

ArchivedIssues会创建一个表,它是Issue表的精确副本。使用它应该很容易

var oldIssueVersion = session.Get<Issue>(newIssueVersion.Id);
session.Delete(oldIssueVersion);

var conflict = new Conflict<Issue>() { Id = Guid.NewGuid(), IssueKey = oldIssueVersion.Key, OriginalEntity = oldIssueVersion, DateOfConflict = DateTime.Now };
session.Save(conflict);
session.Save(newIssueVersion);

查询旧问题将是

var oldIssueVersions = session.CreateCriteria<Issue>("ArchivedIssues")
    .List<Issue>();