使用Typescript / javascript

时间:2017-09-04 07:17:02

标签: c# angularjs entity-framework asp.net-web-api

我在c#中开发了一个服务器端,实体框架作为SQL服务器的提供者。我的服务器正在管理学生和班级之间的多对多关系。

  public class Student
  {

      public List<Course> Courses
      .
      .
  }

   public class Course
   {
         public List<Student> Students
        .
        .
   }

我的客户端是使用Typscript在角度js中开发的。 要与服务器同步,服务器中的每个更改都会通过推送通知(信号器)推送到客户端。

为了缩短响应时间,我的客户端在内存中保留了一种数据库(因为数据量不是很大,少于500条记录)。 我保留了一系列学生,他们每个人都会保留一系列课程:

     Students: { [studentId: number] : Courses } ={}

在那个目标中,我会跟踪所有学生及其在客户方面的课程。

在我的应用程序中,我可以选择从整个系统中删除多个课程。然而,当做这样的事情时,当在服务器端成功完成动作时,当有许多学生时,客户端的处理变得很重。这是因为我需要遍历所有已删除的课程,并且每个课程都会遍历整个学生数组,以便从学生数组中找到并删除这些课程。 (或者首先迭代已删除的课程,然后在学生中迭代) - 两者都很重,需要一段时间。

这有更好的设计吗?我应该以不同的方式处理这个问题吗?

6 个答案:

答案 0 :(得分:1)

有几件事情浮现在脑海中:

  1. 检查您是否真的需要“客户端数据库”。你的后端慢吗?不是premature optimation吗?我认为如果删除此部分,客户端程序的复杂性将大幅下降......只需在需要时直接从服务器获取最新数据。

  2. 重新加载整个“客户数据库”,如果发生重大变化。

  3. 优化您的“客户数据库”。删除几百个项目不应该花费太长时间......您使用的是angular.forEach吗? It could slow you down significantly。你有几百名学生,但只有几个被删除的课程?迭代学生,然后(在迭代内)迭代已删除的课程。伪代码:

    for (student in students) {
        for (deletedCourse in deletedCourses) {
             student.removeCourse(deletedCourse);
        }
    }
    

    而不是这样:

    for (deletedCourse in deletedCourses) {
        for (student in students) {
             student.removeCourse(deletedCourse);
        }
    }
    

    这样,你会迭代更多,浪费时间。但是如果没有源代码,很难知道。

  4. 通常,您应分析您的代码并确定性能问题。根据不同方法需要多长时间登录控制台并相应选择。

答案 1 :(得分:0)

在删除课程后,使用数据库中的更新数据重建学生数组。

答案 2 :(得分:0)

尝试仅在student对象中存储courseID。这样,移除部件的性能可能是可控的 将课程放在单独的对象中,并使用map功能为学生提供课程。

同样如评论所示,您的课程删除代码可能会发挥作用。因此,如果您可以编辑您的问题,那将会很有帮助。

答案 3 :(得分:0)

当然有一种更好的设计,而不仅仅是循环遍历数组:)

实际上,您需要过滤客户端数组(即内存数据库)以排除(删除)由服务器删除的课程。

因此,假设服务器完成了它的工作并删除了一些课程,因此通过SignalR发送了deletedOnServer数组。然后你可以调用客户端功能 - 例如PurgeCourses - 并清理内存数据库。这是一个可能的实现,使用本机JavaScript的Array.prototype.filter()

// Assuming you client side courses are stored here
var clientSideCoursesArray = [];

function PurgeCourses(deletedOnServer) {
    // To get an array of deleted courses ids:
    var deletedCoursesIds = $.map(deletedOnServer, function (x) { return x.id; });

    clientSideCoursesArray = clientSideCoursesArray.filter(function (prev, cur, idx, arr) {
        var isDeletedByServer = deletedCoursesIds.indexOf(cur.id) !== -1;

        return !isDeletedByServer;
    });
}

但是,jQuery.grep()是推荐的方式,因为它经过优化可以更好地执行:

    function PurgeCourses(deletedOnServer) {
        // To get an array of deleted courses ids:
        var deletedCoursesIds = $.map(deletedOnServer, function (x) { return x.id; });

        clientSideCoursesArray = $.grep(clientSideCoursesArray, function (course, index) {
            var isDeletedByServer = $.grep(deletedCoursesIds, course.id).length > 0;

            return isDeletedByServer;
        }, true);
    }

请注意使用倒置 - $.grep()的第四个参数。

答案 4 :(得分:0)

您可以将其存储在webapi服务器内存中的单个对象中并访问它,而不是将其存储在客户端内存中。 singleton object可以在预定义的时间间隔内检查数据库是否有变化(如果您使用带有日期时间比较的最后修改字段,则很少行的代码可以执行此操作)。它可以将整个数据集再次作为单例获取到webapi内存中。

这还可以确保每个客户端使用一致的数据副本。

答案 5 :(得分:0)

您不应该在客户端存储复杂数据,当您拥有服务器时,客户端没有理由发现磁盘空间被盗。如果您的服务器速度不够快,则必须提供更好的服务器。

答案是,你必须做出选择,在客户端重复这个过程(慢慢地)(考虑到最终用户可能有一台坏PC并且速度慢很多)或者只是想一个好的服务器策略处理你的数据。

如果要减少服务器工作,可以查询数据并缓存结果,直到发生变化。当用户更改某些内容时,您再次查询数据库并继续保存数据。

我有一个最后的建议,当你开发一些东西时,你必须认为你将为数十亿用户提供你的产品。考虑到大量用户,您确定要求所有数据是个好主意吗?