0

如何将子对象添加到父集合,同时保持域模型的完整性,而不发出select获取父对象的语句?

我有以下模型:

public class Post
{
    private readonly IList<Comment> _comments = new List<Comment>();
    public virtual IList<Comment> Comments { get { return _comments; } }

    public virtual void AddComment(string text)
    {
        var comment = new Comment
            {
                Post = this,
                Text = text
            };

        _comments.Add(comment);
    }
}

public class Comment
{
    public virtual int Id { get; set; }
    public virtual Post Post { get; set; }
    public virtual string Text { get; set; }
}

这是我目前正在做的事情:

var post = session.Load<Post>(1);
post.AddComment("Test comment.");
transaction.Commit();

这种方法的问题是,当我调用AddComment()代理PostNHibernate 时会加载整个帖子,从而针对数据库发出 select 语句。我想_comments通过总是打电话AddComment()来添加评论来保护列表。

是否可以在不查询父级的情况下保持我的域模型的完整性并将子级添加到父级?

4

2 回答 2

1

如果你inverse=true在 IList 中设置映射Post,那么Comment实体将负责维护关系。像这样的东西应该工作:

var comment = new Comment();
comment.Post = session.Load<Post>(1);
comment.Text = "Test comment";
transaction.Commit();

但是,作为替代方案,请考虑按主键选择是否真的会造成那么大的性能损失;在大多数情况下,它不会。NHibernate 有时会发出一个额外的 SELECT,这是您在手动数据访问层中看不到的。您可以尝试规避这一点,就像您在这里所做的那样,但这可能不值得。考虑为 ORM 的便利性付出的(非常小的)代价。在性能问题出现时处理,而不是之前处理。

于 2013-08-11T01:32:29.027 回答
1

我可以想到几种方法:

  1. 不要映射评论列表,只映射每条评论的帖子。当您需要整个评论列表时,通过查找具有特定父添加到 Nhibernate 集合的所有评论来动态加载它,而无需初始化集合。这将保持您的域模型完整性。

  2. 映射两种方式,但使更新评论的父级,而不是列表。下次您从数据库加载列表时,列表将得到更新。这更有问题,因为您的域在此过程中不正确,但可能仍然可以 - 这取决于您的要求,以及在此过程中是否访问了您的域(我假设您不需要列表,因为您不希望加载它们)

  3. 完全绕过 NHibernate。我曾经不得不做这样的事情。我有一个场景,其中一个父对象有大量的字符串,我需要为每个集合添加更多的字符串。字符串上没有父字段,我不希望将它们包装在对象中。我不记得我是否有其他原因,但我确实有一个非常紧迫的截止日期和严重的性能问题。我创建了一个简单的 SQL 查询来完成这项工作,它做得很好。这不是我引以为豪的解决方案,但这是我觉得 ORM 不完全适合这项工作的工具之一。我担心将来会更改列名或表名,但由于我的映射是使用 Fluent Nhibernate 在代码中完成的,所以问题得到了解决。

于 2013-08-10T12:42:56.127 回答