3

我想创建一个对象代理,类似于 ISession.Load 返回的内容,但初始化了一些字段。对于其他属性,当访问时,代理将从数据库中获取整个对象。考虑以下示例:

public class User
{
    protected User() {

    }

    public User(int id, string username, string email) {
        // ... 
    }

    // initialize the following fields from other datasources
    public virtual int Id { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Email { get; set; }

    // the rest of fields when accessed will trigger a select by id in the database
    public virtual string Field1 { get; set; }
    public virtual string Field2 { get; set; }
    public virtual DateTime Field3 { get; set; }
    public virtual ISet<Comment> Comments { get; set; }
}

在我的例子中,Id、UserName、Email 是众所周知的,所以我可以创建一个包含这些字段的对象代理,而其他字段则保留默认代理行为。除了在数据库中找不到此 id 时抛出异常之外,如果预初始化字段不匹配或静默覆盖它们,我可以抛出异常。我将 NHibernate.ByteCode.Castle 用于代理工厂。

编辑:这样做的目的是能够从可以在其他地方查询的实体(例如,lucene 索引)获得一些投影属性,并避免数据库调用。然后,我不想将这些字段包装在仅包含这些属性子集的自定义组件类中,而是想直接使用代理对象,以便能够在需要时加载其余字段。在最好的情况下,我根本不会访问数据库,但在某些极端情况下,我也想访问其他字段。使用批处理可以大大减少 SELECT N+1 问题的影响。我想使用的一个假设版本的代码是:

        // create User object proxy with some fields initialized
        var user = Session.Load<User>(5, new { UserName = "admin", Email = "admin@company.com" });
        Console.WriteLine(user.Id); // doesn't hit the database
        Console.WriteLine(user.UserName); // doesn't hit the database
        Console.WriteLine(user.FullName); // doesn't hit the database
        if (somecondition) {
            Console.WriteLine(user.Field1); // fetches all other fields 
        }
4

3 回答 3

0

对于非收藏属性,我不会那样做;
加载实体时从数据库中预取它们的成本(通常)非常小,我什至都不会打扰。
对于集合属性,只需将集合获取策略标记为'lazy=true'.

我会考虑做类似事情的唯一情况是当我有大量我不需要的属性时(在你的例子中 - 比如说 Field1..Field20)。
在这种情况下,我会:
1. 将这些属性一起定义为一个组件,或者
2. 创建一个 DTO 以仅获取实体属性的子集。

于 2011-06-14T13:34:06.163 回答
0

您可以在查询中指定一个 Eager fetch 以实际检索所需的关联。这可以根据您使用的查询样式(Criteria、Hql 或 LINQto NH)以不同的方式完成。但关键是改变获取模式。

于 2011-06-14T12:53:10.763 回答
-1

Field1在 properties , Field2, Field3,映射上指定lazy = "true" (或 Not.LazyLoad() 用于 Fluent NHib)Comments可能会有所帮助,但不确定 Select N+1 问题。

另一种方法是为UserName,Email

于 2011-06-14T13:13:46.557 回答