Slauma 솔루션을 사용하여 자식 개체 및 자식 개체 컬렉션을 업데이트하는 데 도움이되는 몇 가지 일반적인 기능을 만들었습니다.
모든 영구 객체가이 인터페이스를 구현합니다.
/// <summary>
/// Base interface for all persisted entries
/// </summary>
public interface IBase
{
/// <summary>
/// The Id
/// </summary>
int Id { get; set; }
}
이를 통해 리포지토리 에서이 두 가지 기능을 구현했습니다.
/// <summary>
/// Check if orgEntry is set update it's values, otherwise add it
/// </summary>
/// <param name="set">The collection</param>
/// <param name="entry">The entry</param>
/// <param name="orgEntry">The original entry found in the database (can be <code>null</code> is this is a new entry)</param>
/// <returns>The added or updated entry</returns>
public T AddOrUpdateEntry<T>(DbSet<T> set, T entry, T orgEntry) where T : class, IBase
{
if (entry.Id == 0 || orgEntry == null)
{
entry.Id = 0;
return set.Add(entry);
}
else
{
Context.Entry(orgEntry).CurrentValues.SetValues(entry);
return orgEntry;
}
}
/// <summary>
/// check if each entry of the new list was in the orginal list, if found, update it, if not found add it
/// all entries found in the orignal list that are not in the new list are removed
/// </summary>
/// <typeparam name="T">The type of entry</typeparam>
/// <param name="set">The database set</param>
/// <param name="newList">The new list</param>
/// <param name="orgList">The original list</param>
public void AddOrUpdateCollection<T>(DbSet<T> set, ICollection<T> newList, ICollection<T> orgList) where T : class, IBase
{
// attach or update all entries in the new list
foreach (T entry in newList)
{
// Find out if we had the entry already in the list
var orgEntry = orgList.SingleOrDefault(e => e.Id != 0 && e.Id == entry.Id);
AddOrUpdateEntry(set, entry, orgEntry);
}
// Remove all entries from the original list that are no longer in the new list
foreach (T orgEntry in orgList.Where(e => e.Id != 0).ToList())
{
if (!newList.Any(e => e.Id == orgEntry.Id))
{
set.Remove(orgEntry);
}
}
}
그것을 사용하려면 다음을 수행하십시오.
var originalParent = _dbContext.ParentItems
.Where(p => p.Id == parent.Id)
.Include(p => p.ChildItems)
.Include(p => p.ChildItems2)
.SingleOrDefault();
// Add the parent (including collections) to the context or update it's values (except the collections)
originalParent = AddOrUpdateEntry(_dbContext.ParentItems, parent, originalParent);
// Update each collection
AddOrUpdateCollection(_dbContext.ChildItems, parent.ChildItems, orgiginalParent.ChildItems);
AddOrUpdateCollection(_dbContext.ChildItems2, parent.ChildItems2, orgiginalParent.ChildItems2);
도움이 되었기를 바랍니다
EXTRA : 별도의 DbContextExtentions (또는 고유 한 컨텍스트 유추) 클래스를 만들 수도 있습니다.
public static void DbContextExtentions {
/// <summary>
/// Check if orgEntry is set update it's values, otherwise add it
/// </summary>
/// <param name="_dbContext">The context object</param>
/// <param name="set">The collection</param>
/// <param name="entry">The entry</param>
/// <param name="orgEntry">The original entry found in the database (can be <code>null</code> is this is a new entry)</param>
/// <returns>The added or updated entry</returns>
public static T AddOrUpdateEntry<T>(this DbContext _dbContext, DbSet<T> set, T entry, T orgEntry) where T : class, IBase
{
if (entry.IsNew || orgEntry == null) // New or not found in context
{
entry.Id = 0;
return set.Add(entry);
}
else
{
_dbContext.Entry(orgEntry).CurrentValues.SetValues(entry);
return orgEntry;
}
}
/// <summary>
/// check if each entry of the new list was in the orginal list, if found, update it, if not found add it
/// all entries found in the orignal list that are not in the new list are removed
/// </summary>
/// <typeparam name="T">The type of entry</typeparam>
/// <param name="_dbContext">The context object</param>
/// <param name="set">The database set</param>
/// <param name="newList">The new list</param>
/// <param name="orgList">The original list</param>
public static void AddOrUpdateCollection<T>(this DbContext _dbContext, DbSet<T> set, ICollection<T> newList, ICollection<T> orgList) where T : class, IBase
{
// attach or update all entries in the new list
foreach (T entry in newList)
{
// Find out if we had the entry already in the list
var orgEntry = orgList.SingleOrDefault(e => e.Id != 0 && e.Id == entry.Id);
AddOrUpdateEntry(_dbContext, set, entry, orgEntry);
}
// Remove all entries from the original list that are no longer in the new list
foreach (T orgEntry in orgList.Where(e => e.Id != 0).ToList())
{
if (!newList.Any(e => e.Id == orgEntry.Id))
{
set.Remove(orgEntry);
}
}
}
}
다음과 같이 사용하십시오.
var originalParent = _dbContext.ParentItems
.Where(p => p.Id == parent.Id)
.Include(p => p.ChildItems)
.Include(p => p.ChildItems2)
.SingleOrDefault();
// Add the parent (including collections) to the context or update it's values (except the collections)
originalParent = _dbContext.AddOrUpdateEntry(_dbContext.ParentItems, parent, originalParent);
// Update each collection
_dbContext.AddOrUpdateCollection(_dbContext.ChildItems, parent.ChildItems, orgiginalParent.ChildItems);
_dbContext.AddOrUpdateCollection(_dbContext.ChildItems2, parent.ChildItems2, orgiginalParent.ChildItems2);