如何使EF首先查询上下文,如果没有找到,查询数据库?

时间:2016-04-28 13:40:08

标签: c# entity-framework

我有一个使用EF向数据库添加大量数据的程序。其中一个数据是一个在数据库中应该是唯一的记录,所以,我有这个指令:

DataWare.Funcionario funcionario = db.Funcionario.Where(f => f.FunRut.Equals(rut)).FirstOrDefault();

如果" funcionario"找不到新的对象,并以这种方式添加到上下文中:

db.Funcionario.Add(funcionario);

这是一个foreach cicle。在某些迭代中,我们遇到相同的" funcionario",上面的Where方法返回null,即使它已经被添加到上下文中。

在foreach之后,我将更改保存到上下文中。

我一直在搜索,我发现该方法总是查询数据库,我可以使用Local属性查询已经在上下文中的对象,但是,这样我有2个问题。首先,它总是仅查询Local实例,因此我需要显式地进行2次调用,以便在上下文中找不到数据库时查询数据库。第二个问题,也就是最糟糕的问题是,当我将SaveChanges调用到上下文时,它会保存许多相同记录的重复项。我不知道为什么。可能这是因为本地和数据库数据未同步。

任何帮助将不胜感激。

由于 海梅

编辑:

这是实际情况:我有一个List<>这实际上为公司员工存储了大量的考勤活动。那个事件来自考勤设备。

我所谈论的foreach是通过该列表的foreach。该事件和工作人员应该在我的数据库中创建,以防它尚不存在。

如果员工不存在,系统会远程调用另一个系统来检索员工信息,然后将该信息保存到我们自己的系统中。如果已添加人员,则应使用该实例而不是创建新实例。顺便说一句,同一个工作人员可以在白天产生几个事件。因此,我将该事件添加到我自己的系统中,以关联找到的员工或新创建的员工。

这是foreach的完整代码供您参考:

        using (DataWare.SistemasBCIEntities db = new DataWare.SistemasBCIEntities())
        {
            bool exito = false;

            foreach (var log in logs.OrderBy(l => l.EnrollNumber))
            {
                string rut = log.EnrollNumber.ToString();
                DataWare.Funcionario funcionario = db.Funcionario.Where(f => f.FunRut.Equals(rut)).FirstOrDefault();
                if (funcionario == null)
                    funcionario = GetPersonFromZKTime(rut, db);

                if (funcionario != null)
                {
                    // Si ya hay un evento para esa hora y ese funcionario, debe continuar con el siguiente
                    DataWare.Evento evento = db.Evento.Where(e => e.EveFechaHora.Equals(log.Date) && e.Funcionario.FunRut.Equals(rut)).FirstOrDefault();
                    if (evento == null)
                    {
                        exito = true;

                        string tipoEvento = String.Empty;
                        if (log.InOutMode == DataWare.Terminal.InOutModeEnum.Check_In || log.InOutMode == DataWare.Terminal.InOutModeEnum.OT_In || log.InOutMode == DataWare.Terminal.InOutModeEnum.Break_In)
                            tipoEvento = "IN";
                        else
                            tipoEvento = "OUT";
                        evento = new DataWare.Evento()
                        {
                            Funcionario = funcionario,
                            EveFechaHora = log.Date,
                            EveTipo = tipoEvento,
                            EveFechaCreacion = DateTime.Now
                        };

                        db.Evento.Add(evento);
                    }
                }
            }

            db.SaveChanges();

            return exito;
        }

2 个答案:

答案 0 :(得分:0)

你可能只是检查是否已设置id,否则设置实体状态如下:

foreach(var rut in source.Distinct()) 
{       
    db.Entry(rut).State = rut.Id == 0 ? 
                               EntityState.Added : 
                               EntityState.Modified;
} 

答案 1 :(得分:0)

我已经将用于查找记录的字段更改为主键,然后我使用了EF的Find方法,它按预期工作。