Fluent Nhibernate Lazy 是否从 Criteria 加载 IList

发布于 2024-10-28 04:57:38 字数 1701 浏览 4 评论 0原文

我想在我公司的应用程序中制作一种“新闻提要”。 在该场景中,用户操作将生成不同类型的“活动”,其他用户将在他们的“新闻提要”中看到。

然而,“活动”并不与所有用户相关,为了确定这种关系,我们有一段复杂的代码。

这是我的 Activity 类,

public class Activity: IActivity
{
    public virtual int Id { get; set; }
    public virtual ActivityType Type { get; set; }
    public virtual User User { get; set; }
    public virtual bool IsVisibleToUser(User userLook)
    {
        // Complex business calculation etc.
        return true;
    }
}

我想获取用户可见的最新 10 条新闻。但由于活动表相当大,并且性能是一个问题,所以我想对此进行最佳实践。

我要做的是获取最后 25 个 Activity,并检查我们是否填写了列表以显示给用户。例如,如果只有 5 个 Activity 对用户可见,我将获得另外 25 个 Activity,依此类推。

IList<Activity> resultList = session.CreateCriteria(typeof(Activity))
                                .SetMaxResults(25)
                                .AddOrder(Order.Desc("Id"))
                                .List<Activity>();

我想知道,如果我得到按 Id 排序的整个列表,并一一检查它是否对用户可见,NHibernate 是否只加载我使用的对象?

IList<Activity> resultList = session.CreateCriteria(typeof(Activity))
                                .AddOrder(Order.Desc("Id"))
                                .List<Activity>();

int count = 0;
foreach( Activity act in resultList){
    if (act.IsVisible(CurrentUser)){
        count++;
        // Do something with act
        if (count == 10)
            break;
    }
}

编辑: 这是 Activity 模型的 ActivityMapping。

public class ActivityMap : ClassMap<Activity>
{
    public ActivityMap()
    {
        Id(x => x.Id);
        Map(x => x.Type).CustomType(typeof(Int32));
        References(x => x.User).Nullable();
    }
}

I want to make a kind of "news feed" in the application of my company.
In the scenario, User actions will generate "Activity" of different kinds, and other users will see in their "news feed".

However, an "Activity" is not related to all users, and to determine the relation, we have a complex piece of code.

Here is my Activity class

public class Activity: IActivity
{
    public virtual int Id { get; set; }
    public virtual ActivityType Type { get; set; }
    public virtual User User { get; set; }
    public virtual bool IsVisibleToUser(User userLook)
    {
        // Complex business calculation etc.
        return true;
    }
}

I want to get latest 10 news that is visible to User. But since the Activity table will be quite huge, and performance is an issue, I want to do the best practice about it.

What i am about to do, is get 25 last Activity, and check if we fill the list to show to user. For example, if only 5 Activity is visible to user, i will get another 25 Activities and so on.

IList<Activity> resultList = session.CreateCriteria(typeof(Activity))
                                .SetMaxResults(25)
                                .AddOrder(Order.Desc("Id"))
                                .List<Activity>();

I want to learn, if I get the whole list ordered by Id, and check one by one if it is visible to User, would NHibernate only loads the objects that i use for me or not?

IList<Activity> resultList = session.CreateCriteria(typeof(Activity))
                                .AddOrder(Order.Desc("Id"))
                                .List<Activity>();

int count = 0;
foreach( Activity act in resultList){
    if (act.IsVisible(CurrentUser)){
        count++;
        // Do something with act
        if (count == 10)
            break;
    }
}

EDIT:
Here is ActivityMapping for Activity model.

public class ActivityMap : ClassMap<Activity>
{
    public ActivityMap()
    {
        Id(x => x.Id);
        Map(x => x.Type).CustomType(typeof(Int32));
        References(x => x.User).Nullable();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

滥情空心 2024-11-04 04:57:38

如果您的问题是生成的 SQL 是什么样子,我的猜测是:

SELECT 
   this_.Id as Id0_0_, 
   this_.ActivityTypeas ActivityType_0_0_, 
   --Other fields
FROM dbo.ActivityType this_ 
WHERE 
   --condition
ORDER BY 
   --condition

既然您提到 Activity 计数很大,您可以利用
ICriteria 的 SetFirstResultSetMaxResult

SetFirstResult(int) 表示您希望获取的第一项的索引,SetMaxResult(int) 表示您希望获取的行数,在您的情况下为 25。

ToList 会一次性加载内存中的所有记录。

[UPDATE] 如果您需要一条一条地返回记录,请使用 Enumerable() -

如果您希望查询返回大量对象,但又不希望如果全部使用它们,您可能会从返回 System.Collections.IEnumerable 的 Enumerable() 方法获得更好的性能。迭代器将使用初始 SQL 查询返回的标识符按需加载对象(n+1 选择总计)。

来源 - 链接

If your question is about how the generated SQL would look like, my guess would be :

SELECT 
   this_.Id as Id0_0_, 
   this_.ActivityTypeas ActivityType_0_0_, 
   --Other fields
FROM dbo.ActivityType this_ 
WHERE 
   --condition
ORDER BY 
   --condition

Since you have mentioned that the Activity count is huge, you can make use of
ICriteria's SetFirstResult and SetMaxResult.

SetFirstResult(int) indicates the index of the first item that you wish to obtain and SetMaxResult(int) indicates the number of rows you wish to get, 25 in your case.

The ToList would load all the records in memory at once.

[UPDATE] If you need the records to be returned one by one, make use of Enumerable() -

If you expect your query to return a very large number of objects, but you don't expect to use them all, you might get better performance from the Enumerable() methods, which return a System.Collections.IEnumerable. The iterator will load objects on demand, using the identifiers returned by an initial SQL query (n+1 selects total).

Source - Link

就此别过 2024-11-04 04:57:38

不,List() 方法将所有内容立即拉入内存。

No, the List() method pulls everything into memory at once.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文