在MVC中,将复杂查询和视图模型传递给会话?

时间:2015-08-20 20:28:37

标签: mysql asp.net-mvc asp.net-mvc-4 session pagination

我有一个视图模型:

 public class UserCollectionView
    {
        public CardCollection CardCollections { get; set; }
        public Card Cards { get; set; }    
    }

我有一个列表视图控制器:

public ActionResult ViewCollection(int? page)
        {
            var userid = (int)WebSecurity.CurrentUserId;
            var pageNumber = page ?? 1;
            int pageSize = 5;                
            ViewBag.OnePageOfCards = pageNumber;
            if (Session["CardCollection"] != null)
            {    
             var paging = Session["CardCollection"].ToString.();
             return View(paging.ToPagedList(pageNumber, pageSize));    
            }                                  
            var viewModel = from c in db.Cards
                            join j in db.CardCollections on c.CardID equals j.CardID
                            where (j.NumberofCopies > 0) && (j.UserID == userid)
                            orderby c.Title
                            select new UserCollectionView { Cards = c, CardCollections = j };

            Session["CardCollection"] = viewModel;
            return View(viewModel.ToPagedList(pageNumber, pageSize));

我正在尝试使用PagedList向结果添加分页。当我没有使用在单个视图中从2个数据库返回数据的查询时,我能够这样做。 As shown here

我的最终结果如下:

     Cards.SeveralColumns   CardCollections.ColumnA   CardCollections.ColumnB 
Row 1 Data from Cards Table  A from CardCollections    B from CardCollections
Row 2 Data from Cards Table  A from CardCollections    B from CardCollections
Row 3 Data from Cards Table  A from CardCollections    B from CardCollections

等等...我收到了一个错误 The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. 我尝试过各种SQL语句,但不能使它适合我的视图模型。在SQL Management Studio中,这会返回正确的结果 Select * from Cards Inner Join CardCollections On Cards.CardID = CardCollections.CardID where CardCollections.UserID = 1 and CardCollections.NumberofCopies > 0;

我需要一种在会话中传递查询的方法,以便分页正常运行。任何建议表示赞赏。 :)

2 个答案:

答案 0 :(得分:2)

简短的回答是,你不能。模型需要是内容的快照,因此您无法跨越边界传递打开的查询(作为会话或直接传递给客户端)。

您所看到的是处理超出其初始使用范围的上下文(汇集var viewmodel的地方)。

话虽如此,如果查询数据是一项昂贵的操作,您可以缓存结果(以节省开销)。基本上,您将整个集合(或至少是集合的一个大部分)存储在session / memorycache中(然后可以将其操作到分页列表中)。有什么影响:

public ActionResult ViewCollection(int? page)
{
  var userId = (int) WebSecurity.CurrentUserId;
  var pageNumber = page ?? 1;
  var pageSize = 5;

  ViewBag.OnePageOfCards = pageNumber;

  var cacheKey = String.Format("ViewCollection[{0}]", userId);
  var entities = GetOrCreateCacheItem<IEnumerable<UserCollectionView>>(cacheKey, () => {
    var query = (from c in db.Cards
                 join j in db.CardCollections on c.CardID equals j.CardID
                 where (j.NumberofCopies > 0) && (j.UserID == userid)
                 orderby c.Title
                 select new UserCollectionView { Cards = c, CardCollections = j }
                )
                .ToList(); // Force fetch from Db so we can cache
  });

  return View(entities.ToPagedList(pageNumber, pageSize));
}

// To give an example of a cache provider; Feel free to change this,
// abstract it out, etc.
private T GetOrCreateCacheItem<T>(string cacheKey, Func<T> getItem)
{
  T cacheItem = MemoryCache.Default.Get(cacheKey) as T;
  if (cacheItem == null)
  {
    cacheItem = getItem();
    var cacheExpiry = DateTime.Now.AddMinutes(5);
    MemoryCache.Default.Add(cacheKey, cacheItem, cacheExpiry);
  }
  return cacheItem;
}

答案 1 :(得分:0)

事实证明,我根本不需要传递查询。如果我让它运行它没有会话工作正常。我不确定为什么这样做但我的搜索查询必须通过。也许是因为我使用viewmodel来执行查询。如果我找到任何东西,我会试验并发布。目前工作代码是:

public ActionResult ViewCollection(int? page)
        {
            var userid = (int)WebSecurity.CurrentUserId;
            var pageNumber = page ?? 1;
            int pageSize = 5;

            ViewBag.OnePageOfCards = pageNumber;
            ViewBag.Rarity_ID = new SelectList(db.Rarities, "RarityID", "Title");
            ViewBag.MainType_ID = new SelectList(db.MainTypes, "MainTypeID", "Title");
            ViewBag.CardSet_ID = new SelectList(db.CardSets, "CardSetID", "Title");
            ViewBag.SubType_ID = new SelectList(db.SubTypes, "SubTypeID", "Title");
            var viewModel = from c in db.Cards
                            join j in db.CardCollections on c.CardID equals j.CardID
                            where (j.NumberofCopies > 0) && (j.UserID == userid)
                            orderby c.Title
                            select new UserCollectionView { Cards = c, CardCollections = j };
            return View(viewModel.ToPagedList(pageNumber, pageSize));