我想创建一个对象代理,类似于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
}
答案 0 :(得分:0)
您可以在查询中指定急切获取以实际检索所需的关联。这可以通过不同的方式完成,具体取决于您使用的查询样式(Criteria,Hql或LINQto NH)。但关键是改变获取模式。
答案 1 :(得分:0)
对于非收集属性,我不会这样做;
加载实体时从数据库中预取它们的成本(通常)很小,甚至不会打扰。
对于集合属性,只需将集合获取策略标记为'lazy=true'
。
我 想要做类似事情的唯一情况是,当我拥有大量不需要的属性时(在你的例子中,比如Field1..Field20)。
在那种情况下,我会:
1.将这些属性一起定义为component或
2.创建DTO以仅获取实体属性的子集。
答案 2 :(得分:-1)
在属性Field1
上指定lazy =“true”(或Fluent NHib的Not.LazyLoad()),Field2
,Field3
,Comments
映射可能会有所帮助,不确定选择N + 1问题。
另一种方法是为UserName
指定lazy =“false”,Email