将EF实体提供给JSON

时间:2016-08-01 18:25:19

标签: c# sql json entity-framework linq

我一直在测试一个函数的性能和代码可读性,该函数将EF实体项列表传递给Ajax调用(JSON)。

这是包含4个备选项(ItemList1,ItemList2,ItemList3和ItemList4)的代码,用于将我的UserNotification实体列表传递给JSON:

public ActionResult GetLatestNotificationItems(int nStart, int nFinish)
    {

        int nCurrentUserId = User.Identity.GetUserId<int>();

        var ItemList1 = (from un in db.UserNotifications
                         where un.UserId == nCurrentUserId
                         orderby un.DateCreated descending, un.Id ascending
                         select new { DateCreated = un.DateCreated, HasBeenSeen = un.HasBeenSeen, Id = un.Id, Message = un.Message, Title = un.Title, UserId = un.UserId, ActionURL = un.ActionURL })
                        .Skip(nStart)
                        .Take(nFinish - nStart + 1).ToList();

        var ItemList2 = db.UserNotifications.Where(U => U.UserId == nCurrentUserId)
            .OrderByDescending(U => U.DateCreated)
            .ThenBy(U => U.Id)
            .Skip(nStart)
            .Take(nFinish - nStart + 1)
            .Select(s => new { DateCreated = s.DateCreated, HasBeenSeen = s.HasBeenSeen, Id = s.Id, Message = s.Message, Title = s.Title, UserId = s.UserId, ActionURL = s.ActionURL }).ToList();

        *//queryGetLatestNotificationItemsReturnType is just a class with the return types.* 
        var ItemList3 = db.Database.SqlQuery<queryGetLatestNotificationItemsReturnType>("SELECT Id, DateCreated, HasBeenSeen, Message, Title, UserId, ActionURL from UserNotifications Where UserID = " +
            "{0} ORDER BY DateCreated DESC, Id ASC OFFSET {1} ROWS FETCH NEXT {2} ROWS ONLY", nCurrentUserId, nStart, (nFinish - nStart + 1))
            .ToList();

        //disable ProxyCreation for "ItemList4" option. (To strip entities into POCO objects without the extra unnecessary EF data)
        db.Configuration.ProxyCreationEnabled = false;
        var ItemList4 = db.UserNotifications.SqlQuery(
            "SELECT Id, DateCreated, HasBeenSeen, Message, Title, UserId, ActionURL from UserNotifications Where UserID = " +
            "{0} ORDER BY DateCreated DESC, Id ASC OFFSET {1} ROWS FETCH NEXT {2} ROWS ONLY", nCurrentUserId, nStart, (nFinish - nStart + 1))
            .ToList();

        db.Configuration.ProxyCreationEnabled = true;

        return Json(ItemList4, JsonRequestBehavior.AllowGet);
    }

执行时间(每次3次):

  • ItemList1:28ms,21ms,16ms
  • ItemList2:22ms,19ms,18ms
  • ItemList3:15ms,4ms,5ms
  • ItemList4:18ms,5ms,7ms

现在,问题是,哪一个是推荐使用的? 因为:

  • ItemList3是最快的执行,但它需要一个POCO 除了EF模型之外的结构创建,而不是RAW SQL LINQ。

  • ItemList4几乎一样快,但它需要使用上下文的ProxyCreationEnabled,也是RAW SQL而不是LINQ。

  • 并且ItemList1和ItemList2都表现不佳,但它们使用了很好的可编辑,更容易阅读LINQ。

1 个答案:

答案 0 :(得分:-1)

你听起来好像在看所有选项......你会考虑QueryFirst吗?

就您的标准而言,对于性能而言,db访问权限是vanilla ADO。没有更快的方法。此外,您不需要创建POCO,它们是在设计时由QueryFirst根据查询返回的模式为您生成的。

你说你喜欢编译linq而不是“raw sql”。您是否在字符串文字中对SQL做出反应?你应该!这种奇怪的文化实践仍在继续,这是一个谜。 QueryFirst允许您将sql 放在自己的文件中。它没有编译为IL,但是在您键入时(使用intellisense)由编辑器验证,在保存文件时由QueryFirst测试运行,并且通常升级到语言状态。然后只需将List<QueryResults>(由生成的Execute()方法返回)传递给序列化程序,然后将其移出。请记住,由于DB会说SQL,因此任何其他选项都将在后台生成SQL。为什么不收回控制权?