自动包含实体框架属性

时间:2018-05-22 18:28:55

标签: c# entity-framework lazy-loading

我的问题的答案可能微不足道,但我无法弄清楚如何去做。

假设我们有以下情况:

具有嵌套属性的DB第一个EF-Entity:

Employee

域类public class Employee { public int ID { get; set;} public IEnumerable<Department> Departments { get; set;} public IEnumerable<JobCandidate> Candidates { get; set;} }

(相关类与此示例无关)

EmployeeService

将业务规则应用于查询的服务类public class EmployeeService private RepoTestEntities1 _Database; public EmployeeService(RepoTestEntities1 database) { _Database = database; } public IQueryable<DomainModels.Employee> GetSalariedEmployeesByDepartmentName(string departmentName) { _Database.Configuration.LazyLoadingEnabled = false; return _Database.Employee .Include(e => e.EmployeeDepartmentHistory) .Include(e => e.JobCandidate) .Include(e => e.EmployeeDepartmentHistory.Select(his => his.Department)) .AsNoTracking() .WhereDepartmentName(departmentName) .WhereSalariedFlag(true) .Select(e => CreateEmployee(e)); } private DomainModels.Employee CreateEmployee(Employee e) { [...] (transform to domain) }

WhereDepartmentName

WhereSalariedFlagIQueryable<Employee>被实现为EmployeeService的扩展方法。

现在问题

假设我需要更多方法,从DbContext检索Employees,我不想使用Lazy加载。

反复调用所有这些内容是多余的,容易出错且乏味。您是否知道一种优雅的方式,即始终包含{{1}}的所有方法所需的属性?

策略模式可能是一种可行的方法吗?

1 个答案:

答案 0 :(得分:0)

如果您确实需要包括所有导航属性,则可以使用这段代码。
如果您需要同时加载集合(并非总是一个好主意),则可以删除代码中的continue语句。
上下文就是您的上下文(如果在上下文中插入此代码,则为this

    public IQueryable<T> IncludeAllNavigationProperties<T>(IQueryable<T> queryable)
    {
        if (queryable == null)
            throw new ArgumentNullException("queryable");

        ObjectContext objectContext = ((IObjectContextAdapter)Context).ObjectContext;
        var metadataWorkspace = ((EntityConnection)objectContext.Connection).GetMetadataWorkspace();

        EntitySetMapping[] entitySetMappingCollection = metadataWorkspace.GetItems<EntityContainerMapping>(DataSpace.CSSpace).Single().EntitySetMappings.ToArray();

        var entitySetMappings = entitySetMappingCollection.First(o => o.EntityTypeMappings.Select(e => e.EntityType.Name).Contains(typeof(T).Name));

        var entityTypeMapping = entitySetMappings.EntityTypeMappings[0];

        foreach (var navigationProperty in entityTypeMapping.EntityType.NavigationProperties)
        {
            PropertyInfo propertyInfo = typeof(T).GetProperty(navigationProperty.Name);
            if (propertyInfo == null)
                throw new InvalidOperationException("propertyInfo == null");
            if (typeof(System.Collections.IEnumerable).IsAssignableFrom(propertyInfo.PropertyType))
                continue;

            queryable = queryable.Include(navigationProperty.Name);
        }

        return queryable;
    }