代码之家  ›  专栏  ›  技术社区  ›  Marc.2377

并行循环中的LINQ到SQL:如何防止重复插入?

  •  0
  • Marc.2377  · 技术社区  · 6 年前

    我在尝试并行化计算代价高昂的API集成时遇到了一些麻烦。

    集成并行查询API并填充 ConcurrentBag 收藏。完成一些处理,然后将其传递给 Parallel.ForEach() 它通过linqtosql与数据库接口。

    有:

    1. 一个平行运行的外环

    2. 通过纪律的内部循环

    3. 在它里面,另一个循环遍历课程。

    问题 我遇到的是:由于任何一节课可能属于多个课程,因此在课程上并行循环意味着有时一节课会被插入多次。

    当前代码如下所示:

    ( externalCourseList 是类型的集合 ConcurrentBag<ExternalCourse> .)

    Parallel.ForEach(externalCourseList, externalCourse =>
    {
        using ( var context = new DataClassesDataContext() )
        {
            var dbCourse = context.Courses.Single( x => x.externalCourseId == externalCourse.courseCode.ToString() );
    
            dbCourse.ShortDesc = externalCourse.Summary;
            //dbCourse.LongDesc = externalCourse.MoreInfo;
            //(etc)
    
            foreach (var externalDiscipline in externalCourse.Disciplines)
            {
                var dbDiscipline = context.Disciplines.Where(
                    x => x.ExternalDisciplineID == externalDiscipline.DisciplineCode.ToString() ).SingleOrDefault();
    
                if (dbDiscipline == null)
                    dbDiscipline = new Linq2SQLEntities.Discipline();
    
                dbDiscipline.Title = externalDiscipline.Name;
                //(etc)
                dbDiscipline.ExternalDisciplineID = externalDiscipline.DisciplineCode.ToString();
    
                if (!dbDiscipline.IsLoaded)
                    context.Disciplines.InsertOnSubmit(dbDiscipline);
    
                // relational table used as one-to-many relationship for legacy reasons
                var courseDiscipline = dbDiscipline.Course_Disciplines.SingleOrDefault(x => x.CourseID == dbCourse.CourseID);
    
                if (courseDiscipline == null)
                {
                    courseDiscipline = new Course_Discipline
                    {
                        Course = dbCourse,
                        Discipline = dbDiscipline
                    };
    
                    context.Course_Disciplines.InsertOnSubmit(courseDiscipline);
                }
    
                foreach (var externalLesson in externalDiscipline.Lessons)
                {
                    /// The next statement throws an exception
                    var dbLesson = context.Lessons.Where(
                        x => x.externalLessonID == externalLesson.LessonCode).SingleOrDefault();
    
                    if (dbLesson == null)
                        dbLesson = new Linq2SQLEntities.Lesson();
    
                    dbLesson.Title = externalLesson.Title;
                    //(etc)
                    dbLesson.externalLessonID = externalLesson.LessonCode;
    
                    if (!dbLesson.IsLoaded)
                        context.Lessons.InsertOnSubmit(dbLesson);
    
                    var disciplineLesson = dbLesson.Discipline_Lessons.SingleOrDefault(
                        x => x.DisciplineID == dbDiscipline.DisciplineID && x.LessonID == dbLesson.LessonID);
    
                    if (disciplineLesson == null)
                    {
                        disciplineLesson = new Discipline_Lesson
                        {
                            Discipline = dbDiscipline,
                            Lesson = dbLesson
                        };
    
                        context.Discipline_Lessons.InsertOnSubmit(disciplineLesson);
                    }
                }
    
            }
    
            context.SubmitChanges();
        }
    }
    );
    

    ( IsLoaded 如所述实现 here .)

    在前面的行中抛出异常 /// 因为同一节课经常被多次插入和调用 .SingleOrDefault() context.Lessons.Where(x => x.externalLessonID == externalLesson.LessonCode) 失败。

    解决这个问题的最好办法是什么?

    谢谢。

    0 回复  |  直到 6 年前