在调用SaveChanges()之前,在Add()之后从上下文中检索实体

e36*_*6M3 6 .net c# entity-framework entity-framework-4

假设我有每个代表一个多行的文件Person,该Person实体有一个identity column是也primary key.假设a Person可以在文件中重复,如果是,也许我想做最后一个条目获胜方案.在下面的示例中,我使用存储库通过社会保险号从数据库中检索人员.问题是,当同一SSN再次出现在文件中时,存储库仍会返回null,即使技术上已经将具有该SSN的人添加到上下文中(SaveChanges尚未被调用).我意识到我可以通过跟踪自己Person已经添加了哪些对象来解决这个问题.我想知道这种情况的最佳做法是什么.谢谢.

foreach(row in fileRows)
{
    Person person = personRepository.GetBySSN(row.SSN);

    if(person == null)
    {
        //insert logic
    }
    else
    {
        //update logic
    }
}

personRepository.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

Ari*_*ini 11

我想我可以给出我在这里给出的相同答案

要保持实体,您通常会DbSet在上下文中将其添加到实体中.

例如

var bar = new Bar();
bar.Name = "foo";
var context = new Context();
context.Bars.Add(bar);
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,查询context.Bars,无法找到刚刚添加的实体

var howMany = context.Bars.Count(b => b.Name == "foo");
// howMany == 0
Run Code Online (Sandbox Code Playgroud)

context.SaveChanges()同一行之后会产生1

DbSet直到他们的分贝坚持似乎察觉到的变化.

幸运的是,每个属性都有DbSet自己的Local属性DbSet,但它反映了所有内存中的操作

var howMany = context.Bars.Local.Count(b => b.Name == "foo");
// howMany == 1
Run Code Online (Sandbox Code Playgroud)

您还可以使用Local添加实体

context.Bars.Local.Add(bar);
Run Code Online (Sandbox Code Playgroud)

并摆脱实体框架的奇怪行为.


e36*_*6M3 -1

我还没有找到任何有关最佳实践的信息,因此我将发布我的解决方案。我知道许多其他帖子提到了这样一个事实:EF 上下文提供了用于查看它并查看特定实体是否处于附加状态的机制。由于我通过存储库进行工作(我的业务层无法直接访问 EF 上下文),因此我的选择是将此类逻辑卸载到存储库中,或者尝试在业务层中解决它。我的感觉是,这项任务实际上是一个业务问题,而不是数据访问层问题。

Dictionary<string, Person> newPeople = ...

foreach(row in fileRows)
{
    Person person;

    //if the person is already tracked by the dictionary, work with it, if not use the repository
    if(!newPeople.TryGetValue(row.SSN, out person))
    {
        person = personRepository.GetBySSN(row.SSN);
    }

    if(person == null)
    {
        //insert logic

        //keep track that this person is already in line for inserting
        newPeople.Add(row.SSN, person);
    }
    else
    {
        //update logic
    }
}

personRepository.SaveChanges();
Run Code Online (Sandbox Code Playgroud)