将子对象添加到父对象而不查询父对象

时间:2013-08-09 22:32:01

标签: nhibernate

如何在保持域模型完整性的同时将子对象添加到父集合中,而不发出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()代理上调用Post时,NHibernate会加载整个帖子,从而针对数据库发出select语句。我想通过始终打电话_comments添加评论来保护AddComment()列表。

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

2 个答案:

答案 0 :(得分:1)

我有几种方法可以想到:

  1. 不要映射评论列表,只映射每条评论的帖子。当您需要整个评论列表时,通过查找具有特定父Add to Nhibernate collection without initializing the collection的所有评论来动态加载它。这将保持您的域模型的完整性。

  2. 映射两种方式,但制作更新注释的父级,而不是列表。下次从db加载时,列表将会更新。这更成问题,因为您的域在此过程中不正确,但可能仍然没问题 - 这取决于您的要求,以及您的域是否在此过程中被访问(我假设您不需要列表,因为您不希望加载它们)

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

答案 1 :(得分: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的便利而支付的(非常小的)价格。当它们出现时,而不是之前处理性能问题。