实体框架在保存实体上的意外行为

时间:2012-10-18 02:05:28

标签: entity-framework entity-relationship

我有两个实体Fisioterapeuta和Paciente,一个Fisioterapeuta有* Pacientes。 当一个添加新的Fisioterapeuta,它确定。

在Paciente表格中,我有一个DropDownList来选择Paciente的Fisioterapeuta,因此,实体Paciente拥有Fisioterapeuta类型的财产。

当添加一名患者时,EF复制(创建另一名)Fisioterapeuta。

我知道这发生了因为Paciente.Fisioterapeuta是!= null,因为我在试图保存Paciente时使用通用存储库,Fisioterapeuta会更进一步。

有没有办法避免这种行为?怎么处理这个?

PS:我使用的是通用存储库,因此我无法覆盖SaveChanges或在保存时进行验证。

EDIT1

@Brad Christie sugestion我做了以下事情:

Paciente p = (Paciente)grdEdicao.DataContext; //here the DataContext brings me the Fisioterapeuta on the property p.Fisioterapeuta

p.Fisioterapeuta = Repository<Fisioterapeuta>.GetByID((int)comboFisioterapeutas.SelectedValue); // i try to set the Fisioterapeuta getting it from the repository.

此更改无法解决我的问题。

EDIT2

我创建了一个github项目来测试它,这里是https://github.com/Ewerton/RelatedEntities_EF

2 个答案:

答案 0 :(得分:0)

您有可能在插入时重新创建Medic(而不是将其分配给先前建立的Medic),因此EF认为需要创建新条目以满足插入。

确保为Patient.Medic分配对数据库中已存在的Medic的引用。 e.g。

patient.Medic = Medics.SingleOrDefault(x => x.Name = medicName);

假设medicName是从下拉列表中传递的值。或者(可能更好)你应该参考医生的ID并使用它来获取参考。

所以,一起:

<label for="name">
  Patient Name:
  <input type="text" id="name" name="name" />
</label>
<label for="medic">
  Medic:
  <select id="medic" name="medic">
    <option value="">Please select one</option>
    <option value="1">Dr. Smith</option>
    <option value="2">Dr. Jones</option>
  </select>
</label>
<input type="submit" value="Save" />

然后:

Patient patient = new Patient {
  Name = name,
  Medic = Medics.SingleOrDefault(x => x.Id == medic)
};

答案 1 :(得分:0)

好的,我会回答我自己的问题(我不喜欢这样做)。

我最后得出以下意见,如果我与EF合作,我有两种方法,如下:

不使用参照约束

在这种情况下,在EDMX中设计实体时,只需从工具框中选择关联,单击父实体,将该行拖动到子实体,然后创建关联,这样,您将需要注意附加和分离的实体(如果你使用通用存储库,像我一样,你将以我的问题中描述的相同问题结束)。 使用这种方法,您将编写这样的代码。

        Fisioterapeuta f2 = new Fisioterapeuta();
        using (var ctx = new Model1Container())
        {
            f2 = ctx.Set<Fisioterapeuta>().FirstOrDefault();
        }

        Paciente p = new Paciente();
        p.Nome = "Paciente1";
        p.Fisioterapeuta = f2; // here you associate a Fisioterapeuta to a Paciente

当您尝试保存“p”实体时,也会在数据库中创建“f2”实体。避免它的一种方法是管理“f2”实体的状态,注意它是否被附加或分离。

使用参照约束

在这种情况下,在EDMX中设计实体时,不要在工具框中选择关联,单击EDMX的空白区域,添加新关联,填写表单,别忘了标记选项“添加外键'YourEntity'实体的财产“。通过这种方式,我的实体Paciente将拥有FisioterapeutaId属性,这是Fisioterapeuta的外键,我可以编写这样的代码

        Fisioterapeuta f2 = new Fisioterapeuta();
        using (var ctx = new Model1Container())
        {
            f2 = ctx.Set<Fisioterapeuta>().FirstOrDefault();
        }

        Paciente p = new Paciente();
        p.Nome = "Paciente1";
        //HERE ARE THE TRICK. I MANAGE THE ID OF THE RELATED ENTITIE, I DONT LET THIS WORK FOR EF.
        p.FisioterapeutaId = f2.Id;

请注意,这样我只设置了“p”对象的FisioterapeutaId。在这种情况下,当我保存“p”对象时,将不再创建Fisioterapeuta实体。

结论

不存在正确的方法,你需要自己选择自己的方式。

PS:我在GitHub中更新了项目,这里是链接https://github.com/Ewerton/RelatedEntities_EF