You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Entity Framework泛型类:实现所有子实体重新加载

Solution for Reloading Nested Entities in Entity Framework 6

Since you’ve got a multi-level one-to-many hierarchy (tblProjects → tblLines → tblGroups → tblStations...) where all entities inherit from TblBase, we can build a generic reloading utility that recursively refreshes any entity along with all its nested child collections. This leverages EF6's context entry APIs and works seamlessly with your base class structure.

Generic Entity Reloader Implementation

Here's a static extension class that adds reloading functionality to your DbContext, tailored to your inherited TblBase entities:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Reflection;

public static class EntityReloader
{
    /// <summary>
    /// Reloads a single entity and all its nested child collections recursively
    /// </summary>
    /// <typeparam name="TEntity">Type of entity (must inherit from TblBase)</typeparam>
    /// <param name="context">Your EF DbContext</param>
    /// <param name="entity">Entity to reload</param>
    public static void ReloadWithChildren<TEntity>(this DbContext context, TEntity entity) 
        where TEntity : TblBase
    {
        if (entity == null) return;

        // Refresh the parent entity itself
        var entityEntry = context.Entry(entity);
        entityEntry.Reload();

        // Get all one-to-many navigation properties (ICollection<T> types)
        var childCollectionProps = entityEntry.NavigationProperties
            .Where(np => typeof(ICollection<>).IsAssignableFrom(np.PropertyType))
            .Select(np => np.Name);

        foreach (var propName in childCollectionProps)
        {
            // Load the child collection if it isn't already loaded
            entityEntry.Collection(propName).Load();

            // Get the collection instance and recursively reload each child
            var childEntities = entityEntry.Property(propName).CurrentValue as IEnumerable<TblBase>;
            if (childEntities == null) continue;

            foreach (var child in childEntities)
            {
                context.ReloadWithChildren(child);
            }
        }
    }

    /// <summary>
    /// Reloads a collection of entities and all their nested child collections
    /// </summary>
    /// <typeparam name="TEntity">Type of entity (must inherit from TblBase)</typeparam>
    /// <param name="context">Your EF DbContext</param>
    /// <param name="entities">Collection of entities to reload</param>
    public static void ReloadWithChildren<TEntity>(this DbContext context, IEnumerable<TEntity> entities) 
        where TEntity : TblBase
    {
        if (entities == null) return;

        foreach (var entity in entities)
        {
            context.ReloadWithChildren(entity);
        }
    }
}

How It Works

  1. Base Entity Reload: First, it refreshes the parent entity using DbEntityEntry.Reload(), pulling the latest database data into your entity instance.
  2. Child Collection Detection: It identifies all ICollection<T> navigation properties (these are the one-to-many child sets in your hierarchy, like tblProjects.Lines or tblLines.Groups).
  3. Recursive Child Reload: For each child collection, it loads the data (if not already loaded) and then recursively calls ReloadWithChildren on every child entity—ensuring every level of your hierarchy gets refreshed.
  4. INotifyPropertyChanged Compatibility: Since your TblBase implements INotifyPropertyChanged, property setters will trigger change notifications automatically after reloading, so UI bindings update without extra work.

Usage Examples

Reload a Single Project and All Its Children

using (var context = new YourDbContext())
{
    // Fetch a project (could be any entity in your hierarchy)
    var targetProject = context.tblProjects.FirstOrDefault(p => p.ID == 42);
    
    // Refresh the project + all lines, groups, stations, etc.
    context.ReloadWithChildren(targetProject);
}

Reload a Collection of Entities

using (var context = new YourDbContext())
{
    var projectsToRefresh = context.tblProjects.Where(p => p.COID == 5).ToList();
    
    // Refresh all projects in the list and their nested children
    context.ReloadWithChildren(projectsToRefresh);
}

Key Notes

  • Navigation Property Filtering: The code targets all ICollection<T> navigation properties. If you have non-navigation ICollection properties, add a filter (e.g., check np.IsNavigation or use a custom attribute to mark navigation properties).
  • Performance Considerations: For large datasets or deep hierarchies, this results in multiple database queries (N+1 pattern). For initial loading, use Include chains (e.g., context.tblProjects.Include(p => p.Lines.Select(l => l.Groups.Select(g => g.Stations)))), but this reloader is ideal for refreshing existing entity instances.
  • Context Lifecycle: Use the same DbContext instance that originally fetched the entities—EF6 tracks entities per context, so reloading with a different context won’t update your existing instances.

内容的提问来源于stack exchange,提问作者PigSpider

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:53:21