【问题标题】:Best alternative to deliver EF Entities to JSON将 EF 实体传递到 JSON 的最佳替代方案
【发布时间】:2016-08-01 18:25:19
【问题描述】:

我一直在测试将 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。

【问题讨论】:

  • 过早的优化是万恶之源。将 LINQ 编译成 SQL 的性能较差是否会导致用户体验问题?如果没有,不要费心让它更快。

标签: c# sql json entity-framework linq


【解决方案1】:

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

就您的标准而言,就性能而言,数据库访问是普通 ADO。没有更快的方法。此外,您不需要创建 POCO,它们是 QueryFirst 在设计时根据您的查询返回的架构为您生成的。

你说你喜欢编译的 linq 而不是“原始 sql”。您是否对字符串文字中的 SQL 做出反应?你应该!这种奇怪的文化习俗仍在继续是一个谜。 QueryFirst 允许您将您的 sql 放在它自己的文件中。它没有编译为 IL,但它在您键入时由编辑器验证(使用智能感知),在您保存文件时由 QueryFirst 测试运行,并且通常提升为一种语言的状态。然后只需将List&lt;QueryResults&gt;(由生成的Execute() 方法返回)传递给您的序列化程序并离开那里。请记住,由于数据库使用 SQL,因此任何其他选项都将在幕后生成 SQL。为什么不收回控制权?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多