实体框架添加了太多记录

时间:2013-07-02 14:54:04

标签: c# linq entity-framework

编辑:有关正常工作的代码,请参阅此问题的底部。

我有两个表,即患者和药物,我正在使用数据Feed进行更新。我获得了当前的患者列表,然后根据需要迭代并更新或插入记录。这没有问题。

当我迭代该患者目前的药物时,麻烦来了。我最终获得了原始患者的多份副本。药物记录按预期传输(记录本身不会改变,因此插入新记录并忽略现有记录)。我最终得到了原始患者记录(从下面的UpdatePatients()插入),然后是每个药物记录的另一个患者记录。每个药物记录最终都有一个独特的PatientId。

班级定义:

public class Patient
{
    public int PatientId { get; set; }

    [Required]
    public int FacilityNumber { get; set; }

    [Required]
    public int PatNo { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public int Age { get; set; }

    [Required]
    public string Gender { get; set; }

    [Required]
    public DateTime VentStart { get; set; }

    [Required]
    public DateTime VentEnd { get; set; }

    [Required]
    public DateTime AdmitDate { get; set; }

    public DateTime? DischargeDate { get; set; }
}

public class Drug
{
    public int DrugId { get; set; }

    [Required]
    public int DrugDDI { get; set; }

    [Required]
    public int OrderId { get; set; }

    [Required]
    public string DrugName { get; set; }

    [Required]
    public DateTime DispenseDate { get; set; }

    [Required]
    public double UnitsDispensed { get; set; }

    [ForeignKey("Patient")]
    public int PatientId { get; set; }
    public virtual Patient Patient { get; set; }
}

违规代码:

private static void UpdatePatients()
{
    var Patients = DB2Patient.GetPatients();

    foreach (Patient p in Patients)
    {
        using (var PatientContext = new VAEContext())
        {
            var ExistingPatientRecord = PatientContext.Patients.FirstOrDefault(
                ep => ep.PatNo == p.PatNo
            );
            if (ExistingPatientRecord != null)
            {
                ExistingPatientRecord.VentEnd = p.VentEnd;
                ExistingPatientRecord.DischargeDate = p.DischargeDate;
                PatientContext.SaveChanges();
            }
            else
            {
                PatientContext.Patients.Add(p);
                PatientContext.SaveChanges();
            }
        }
        UpdateDrugs(p);
    }
}

private static void UpdateDrugs(Patient p)
{
    var Drugs = DB2Drug.GetDrugs(p.PatNo);
    foreach (Drug d in Drugs)
    {
        using (var DrugContext = new VAEContext())
        {
            var ExistingDrugRecord = DrugContext.Drugs.FirstOrDefault(
                ed => ed.DrugDDI == d.DrugDDI &&
                      ed.DispenseDate == d.DispenseDate &&
                      ed.OrderId == d.OrderId
            );
            if (ExistingDrugRecord == null)
            {
                d.Patient = p;
                DrugContext.Drugs.Add(d);
                DrugContext.SaveChanges();
            }
        }
    }
}

编辑:工作代码:

private static void UpdatePatients()
{
    var Patients = DB2Patient.GetPatients();

    using (var db = new VAEContext())
    {
        foreach (Patient p in Patients)
        {
            var ExistingPatientRecord = db.Patients.FirstOrDefault(
                ep => ep.PatNo == p.PatNo
            );
            if (ExistingPatientRecord != null)
            {
                ExistingPatientRecord.VentEnd = p.VentEnd;
                ExistingPatientRecord.DischargeDate = p.DischargeDate;
            }
            else
            {
                db.Patients.Add(p);
            }
            UpdateDrugs(p, db);
        }
        db.SaveChanges();
    }
}

private static void UpdateDrugs(Patient p, VAEContext ctx)
{
    var Drugs = DB2Drug.GetDrugs(p.PatNo);
    foreach (Drug d in Drugs)
    {
        var ExistingDrugRecord = ctx.Drugs.FirstOrDefault(
            ed => ed.DrugDDI == d.DrugDDI &&
                  ed.DispenseDate == d.DispenseDate &&
                  ed.OrderId == d.OrderId
        );
        if (ExistingDrugRecord == null)
        {
            d.Patient = p;
            ctx.Drugs.Add(d);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

为什么每次需要插入新的上下文?方法UpdatePatientsUpdateDrugs都是私有的,您可以对所有链接操作使用相同的上下文,我相信您不会获得重复项:

private static void UpdateDrugs(Patient p, VAEContext context) 

...

此外,可能没有必要节省每种药物,这样做可能会降低性能,并且在数据完整性方面做得不多。考虑每个链接更新保存一次上下文更改(比如在UpdatePatients中调用UpdateDrugs之后)

除此之外,您可以查看ObjectContext.Attach及相关方法,了解如何将Patient对象链接到新创建的Drugs上下文实例

http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.attach.aspx