在DB中获取双重数据

时间:2018-05-29 19:14:44

标签: c# asp.net-mvc entity-framework

我从2个数据库中提取学生数据。 1来自在线SOAP API,可以处理异步调用,1来自本地数据库,其中旧服务不支持异步。
我比较了这些数据库,并通过EF在本地sqlDB中编写差异。

问题:
我的EF DB中有两个条目。他将正确的数据和数量放在方法中的数组中,但看起来一旦他命中db.savechanges(),他就会跳回几行并再次保存。
我甚至不知道这个额外的线程来自哪里。

一些代码可能仍然存在于众多尝试中以解决它。例如,我尝试使用addrange,但是当他尝试添加FullVarianceList时出现错误。

public async Task<bool> FullStudentCompare(string date) //format DD/MM/YYYY
{
    try
    {
        //DB context
        using (var db = new SchoolDbContext())
        {
            //GET DATA
            //SMT (async)
            List<SmtStudent> smtStdudentList = await GetAllSmartschoolStudents();
            //Wisa (sync)
            //on date, or if emty on current systemdate
            List<WisaStudent> wisaList;
            if (date == "")
            {
                wisaList = GetWisaStudentData(DateTime.Now.ToShortDateString());
            }
            else
            {
                wisaList = GetWisaStudentData(date);
            }


            //Flags and props needed for DB entry after compare
            bool existsInLocalDb = false;
            List<Variance> vList = new List<Variance>();
            //Full list to add to DB outside foreach
            List<Variance> fullVarianceList = new List<Variance>();
            //Full List of new Students to write to DB outside foreach
            List<DbStudent> fullStudentList = new List<DbStudent>();

            //Compare lists
            foreach (WisaStudent wstd in wisaList)
            {
                //determine correct classCode
                string klasCode;
                if (wstd.klasgroep.Trim() == "Klasgroep 00")
                {
                    klasCode = wstd.klas.Trim();
                }
                else
                {
                    klasCode = wstd.klasgroep.Trim();
                }


                //Create SmtStudent object for compare
                SmtStudent tempStd = new SmtStudent(true,
                                                    wstd.voornaam.Trim(),
                                                    wstd.naam.Trim(),
                                                    wstd.stamboeknummer.Trim(),
                                                    wstd.geslacht.Trim(),
                                                    wstd.geboortedatum.Trim(),
                                                    wstd.straat.Trim(),
                                                    wstd.huisnummer.Trim(),
                                                    wstd.busnummer.Trim(),
                                                    wstd.postcode.Trim(),
                                                    wstd.gemeente.Trim(),
                                                    wstd.emailadres.Trim(),
                                                    wstd.GSM_nummer.Trim(),
                                                    wstd.levensbeschouwing.Trim(),
                                                    wstd.coaccountmoedervoornaam.Trim(),
                                                    wstd.coaccountmoedernaam.Trim(),
                                                    wstd.coaccountmoederemailadres.Trim(),
                                                    wstd.coaccountmoederGSM_nummer.Trim(),
                                                    wstd.coaccountvadervoornaam.Trim(),
                                                    wstd.coaccountvadernaam.Trim(),
                                                    wstd.coaccountvaderemailadres.Trim(),
                                                    wstd.coaccountvaderGSM_nummer.Trim(),
                                                    klasCode,
                                                    wstd.nationaliteit,
                                                    wstd.geboorteGemeente,
                                                    wstd.geboorteLand
                                                    );


                //Find matching SmtStudent
                SmtStudent smtStd = smtStdudentList.Find(i => i.Internnummer == wstd.stamboeknummer);


                //Find matching Std in local DB
                DbStudent dbStd = await db.Students.Where(i => i.Stamboeknummer == wstd.stamboeknummer).FirstOrDefaultAsync();

                //if none exists in the local DB create an entity to update and write to DB
                if (dbStd == null)
                {
                    dbStd = new DbStudent(wstd.voornaam.Trim(),
                                             wstd.naam.Trim(),
                                             wstd.stamboeknummer.Trim(),
                                             wstd.geslacht.Trim(),
                                             wstd.geboortedatum.Trim(),
                                             wstd.straat.Trim(),
                                             wstd.huisnummer.Trim(),
                                             wstd.busnummer.Trim(),
                                             wstd.postcode.Trim(),
                                             wstd.gemeente.Trim(),
                                             wstd.emailadres.Trim(),
                                             wstd.GSM_nummer.Trim(),
                                             wstd.levensbeschouwing.Trim(),
                                             wstd.coaccountmoedervoornaam.Trim(),
                                             wstd.coaccountmoedernaam.Trim(),
                                             wstd.coaccountmoederemailadres.Trim(),
                                             wstd.coaccountmoederGSM_nummer.Trim(),
                                             wstd.coaccountvadervoornaam.Trim(),
                                             wstd.coaccountvadernaam.Trim(),
                                             wstd.coaccountvaderemailadres.Trim(),
                                             wstd.coaccountvaderGSM_nummer.Trim(),
                                             klasCode,
                                             wstd.loopbaanDatum,
                                             wstd.nationaliteit,
                                             wstd.geboorteGemeente,
                                             wstd.geboorteLand
                                             );

                    db.Students.Add(dbStd);
                    fullStudentList.Add(dbStd);
                }
                else
                {
                    existsInLocalDb = true;
                }

                if (smtStd == null)
                {
                    //Std doesn't exist in Smt -> New student
                    dbStd.IsNewStudent = true;
                    dbStd.ClassMovement = true;

                    //remove from wisaList
                    wisaList.Remove(wstd);
                }
                else
                {
                    //clear vlist from previous iterations
                    vList.Clear();

                    //get all properties on the obj, cycle through them and find differences
                    PropertyInfo[] props = smtStd.GetType().GetProperties();

                    vList.AddRange(props.Select(f => new Variance
                    {
                        Property = f.Name,
                        ValueA = f.GetValue(smtStd),
                        ValueB = f.GetValue(tempStd),
                        Checked = false
                    })
                       .Where(v => !v.ValueA.Equals(v.ValueB) && v.ValueB != null)
                       .ToList());


                    //If the users allrdy exists in LocalDb delete all previously recorded variances
                    if (existsInLocalDb)
                    {
                        if (db.Variances.Where(j => j.Student.StudentId.Equals(dbStd.StudentId)).FirstOrDefault() != null)
                        {                            //if the student allready exists we will recreate the variancelist, hence deleting all current items first
                            List<Variance> existingList = db.Variances.Where(j => j.Student.StudentId.Equals(dbStd.StudentId)).ToList();
                            foreach (Variance v in existingList)
                            {
                                db.Variances.Remove(v);
                            }
                        }
                    }

                    //Add new variances if vList is not empty
                    if (vList.Count > 0)
                    {
                        //Check if KlasCode is a variance -> set classmovement to true
                        if (vList.Where(i => i.Property == "KlasCode").FirstOrDefault() != null)
                        {
                            dbStd.ClassMovement = true;
                        }
                        else
                        {
                            dbStd.ClassMovement = false;
                        }

                        //add the StudentObject to the variance to link them 1-many
                        foreach (Variance v in vList)
                        {
                            v.Student = dbStd;
                            fullVarianceList.Add(v);
                            db.Variances.Add(v);
                        }
                    }
                }
            }

            //add the full lists of variances and new students to DB
            //db.Variances.AddRange(fullVarianceList);
            //db.Students.AddRange(fullStudentList);

            db.SaveChanges();

            return true;
        }
    }
    catch(Exception ex)
    {
        return false;
    }
}

1 个答案:

答案 0 :(得分:0)

有几件事:

  1. 重要的是要理解EF使用一个工作模式单元,在调用SaveChanges之前,实体的任何更改都不会持久化,这解释了“一旦他命中db.Savechanges(),他就会跳回来“现象。

  2. 如果您具有1对多的关系,并且您将实体集合分配给另一个实体上的导航属性,然后将该父实体添加到DbContext,则EF也会标记要添加的子实体。在您的情况下,dbStd添加在“db.Students.Add(dbStd);”行中并在“v.Student = dbStd;”行。这很可能是造成重复的原因。