实体框架中外部列表​​中.skip()的最佳方法

时间:2018-12-05 23:20:38

标签: c# entity-framework

我有2张桌子:

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        return userIdentity;
    }

    [ForeignKey("ApplicationUserId")]
    public virtual ICollection<ApplicationUserNotification> ApplicationUserNotifications { get; set; }
}

public class ApplicationUserNotification
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    [StringLength(64)]
    public string ApplicationUserId { get; set; }
    [ForeignKey("ApplicationUserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }
}

我想为用户显示前10条通知,并在用户向下滚动时使用同一视图加载后10条通知。

public ActionResult UserNotications(int skip = 0, int take = 10)
{
    var db = new ApplicationDbContext();
    var user = db.Users.FirstOrDefault(a => a.Id == User.Identity.GetUserId());
    var list = user.ApplicationUserNotifications.Skip(skip).Take(take).ToList();
    return View(list);
}

可是说:

'ICollection'不包含'Skip'的定义,最佳扩展方法重载'Queryable.Skip(IQueryable,int)'需要类型为'IQueryable'的接收器

在不更改代码以直接从用户通知表中查询的情况下,解决此问题的最佳方法是什么?该代码的实际用法使用用户类,因此,如果我可以通过用户对象访问用户通知,那就更好了。

我原本以为会有很多问题,但是搜索引擎似乎跳过了“跳过”一词,所以我对此一无所知。

====================

mick的更新,我在视图中使用它,并且有一个静态对象,可以在其中访问名为“当前”的用户对象:

@{
    Layout = null;
    var skip = Convert.ToInt32(Request["Skip"] ?? "0");
    var take = Convert.ToInt32(Request["Take"] ?? "10");
}

@foreach (var item in Current.User.UserNotifications.Skip(skip).Take(take))
{
    @Html.Partial(Enum.GetName(typeof(Kiteshoot.Enums.NotificationType), item.NotificationType), item)
}

<div class="UserNotificationsEndOfList" data-index="@(skip + take)"></div>

我真的不知道为什么,但是错误已经神奇消失了,我想的太久了,对不起。但是正如Stijn所说,这不会跳过查询,而只会跳过内存中的列表,因此回到平方。

1 个答案:

答案 0 :(得分:1)

如果您要使用跳过并仅从数据库中加载部分通知,请使用...

DbSet<ApplicationUserNotification>()
    .Where(n => n.ApplicationUserId == User.Identity.GetUserId())
    .Skip(() => skip)
    .Take(() => take)
    .ToList()

如果您想知道为什么用.Skip(()=> skip)而不是.Skip(skip),请尝试两种方法,然后看看使用SQL Profiler或其他查询监视工具生成的SQL。您会看到.Skip(()=> skip)会导致参数化查询,而.Skip(skip).Take(take)将烘烤skip的值并进入查询文本,这将减少对SQL的点击计划缓存,导致分页时性能变差。