我有一个程序,它使用 EF 向数据库添加大量数据。其中一个数据是数据库中应该是唯一的记录,所以,我有这个指令:
DataWare.Funcionario funcionario = db.Funcionario.Where(f => f.FunRut.Equals(rut)).FirstOrDefault();
如果未找到"funcionario",则创建一个新对象并按以下方式添加到上下文中:
db.Funcionario.Add(funcionario);
这是在一根蝴蝶里。当在某些迭代中,我们遇到相同的"funcionario"时,上面的 Where 方法返回 null,即使它已经添加到上下文中。
在foreach之后,我保存了对上下文的更改。
我一直在搜索,我发现该方法总是查询数据库,我可以使用 Local 属性来查询上下文中已有的对象,但是,这样我就有 2 个问题。首先,它始终只查询本地实例,因此我需要显式进行 2 次调用,以便在上下文中找不到数据库的情况下查询数据库。第二个问题,也是最糟糕的问题,是当我调用 SaveChanges 到上下文时,它会保存相同记录的许多重复项。我不知道为什么。也许这是由于本地和数据库数据未同步造成的。
任何帮助将不胜感激。
谢谢海梅
编辑:
这是实际场景:我有一个列表<>它实际上为公司员工存储了大量考勤事件。该事件来自考勤设备。
我所说的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;
}
您可能可以检查是否已设置 id,否则将实体状态设置为如下:
foreach(var rut in source.Distinct())
{
db.Entry(rut).State = rut.Id == 0 ?
EntityState.Added :
EntityState.Modified;
}
我已经将用于查找记录的字段更改为主键,然后我使用了 EF 的 Find 方法,它按预期工作。