[英]Entity Framework - Get Updated DB set from context before SaveChanges() is called to add/remove entities
[英]Retrieving entity from context after Add() yet before SaveChanges() has been called
假設我有一個包含多個行的文件,每個行代表一個Person
, Person
實體有一個identity column
,它也是primary key
。 假設一個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();
我想我可以給出我在這里給出的相同答案
要持久保存實體,通常會在上下文中將其添加到DbSet
中。
例如
var bar = new Bar();
bar.Name = "foo";
var context = new Context();
context.Bars.Add(bar);
令人驚訝的是,查詢context.Bars
,無法找到剛剛添加的實體
var howMany = context.Bars.Count(b => b.Name == "foo");
// howMany == 0
在context.SaveChanges()
,同一行將產生1
DbSet
似乎沒有意識到改變,直到它們持久存在db。
幸運的是,每個DbSet
都有一個Local
屬性,就像DbSet
本身一樣,但它反映了所有內存中的操作
var howMany = context.Bars.Local.Count(b => b.Name == "foo");
// howMany == 1
您還可以使用Local
添加實體
context.Bars.Local.Add(bar);
並擺脫實體框架的奇怪行為。
修改GetBySSN
,如下所示:
public Person GetBySSN(string ssn)
{
Person p = context.ObjectStateManager
.GetObjectStateEntries(~EntityState.Deleted)
.Where(e => !e.IsRelationship)
.Select(e => e.Entity)
.OfType<Person>()
.SingleOrDefault(p => p.SSN = ssn);
if (p == null)
{
p = context.People.SingleOrDefault(p => p.SSN = ssn);
}
return p;
}
如果你想去Ladislav的路線並查詢ObjectStateManager,那么你可能希望使用如下的擴展方法:
public static IEnumerable<TEntity> LoadedEntities<TEntity>(this ObjectContext Context)
{
return Context.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Unchanged)
.Where(e => !e.IsRelationship).Select(e => e.Entity).OfType<TEntity>();
}
這將允許你做這樣的事情:
Person p = context.LoadedEntities<Person>().SingleOrDefault(p => p.SSN = ssn);
if (p != null)
return p;
return context.People.SingleOrDefault(p => p.SSN = ssn);
我沒有找到任何關於最佳實踐的內容,所以我會發布我的解決方案。 我知道很多其他帖子都提到了這樣一個事實,即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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.