Converting List to EntityFramework column/field list

前端 未结 2 1215
青春惊慌失措
青春惊慌失措 2020-12-21 09:17

Using EntityFramework, I can get a list of entities of a certain type using the following syntax:

List customers = ((IQueryable

        
相关标签:
2条回答
  • 2020-12-21 09:28

    You can use dynamic linq, check it in here. It is also available on nuget

    0 讨论(0)
  • 2020-12-21 09:44

    I suggest dynamic linq as @Cuong already posted.

    But for simple Select projections and as a hand-made exercise in expressions...

    Using LinqRuntimeTypeBuilder from How to create LINQ Expression Tree to select an anonymous type
    (see the comments there for 'why' is that necessary)

    And add this...

    public static IQueryable SelectDynamic(this IQueryable source, IEnumerable<string> fieldNames)
    {
        Dictionary<string, PropertyInfo[]> sourceProperties = new Dictionary<string, PropertyInfo[]>();
        foreach (var propertyPath in fieldNames)
        {
            var props = propertyPath.Split('.');
            var name = props.Last();
            PropertyInfo[] infos;
            if (sourceProperties.TryGetValue(name, out infos))
                name = string.Join("", props);
            sourceProperties[name] = source.ElementType.GetDeepProperty(props);
        }
    
        Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicType(sourceProperties.ToDictionary(x => x.Key, x => x.Value.Last().PropertyType));
    
        ParameterExpression sourceItem = Expression.Parameter(source.ElementType, "t");
        IEnumerable<MemberBinding> bindings = dynamicType.GetFields()
            .Select(p => Expression.Bind(p, sourceItem.MakePropertyExpression(sourceProperties[p.Name]))).OfType<MemberBinding>();
    
        Expression selector = Expression.Lambda(Expression.MemberInit(
            Expression.New(dynamicType.GetConstructor(Type.EmptyTypes)), bindings), sourceItem);
    
        MethodCallExpression selectExpression = Expression.Call(typeof(Queryable), "Select", new Type[] { source.ElementType, dynamicType }, Expression.Constant(source), selector);
        return Expression.Lambda(selectExpression).Compile().DynamicInvoke() as IQueryable;
    }
    
    public static PropertyInfo[] GetDeepProperty(this Type type, params string[] props)
    {
        List<PropertyInfo> list = new List<PropertyInfo>();
        foreach (var propertyName in props)
        {
            var info = type.GetProperty(propertyName);
            type = info.PropertyType;
            list.Add(info);
        }
        return list.ToArray();
    }
    
    public static Expression MakePropertyExpression(this ParameterExpression sourceItem, PropertyInfo[] properties)
    {
        Expression property = sourceItem;
        foreach (var propertyInfo in properties)
            property = Expression.Property(property, propertyInfo);
        return property;
    }
    

    Use it like e.g.:

    public static IEnumerable<object> 
        SelectAsEnumerable(this IQueryable entitySet, params string[] propertyPath)
    {
        return entitySet.SelectDynamic(propertyPath) as IEnumerable<object>;
    }
    var list = db.YourEntity.SelectAsEnumerable("Name", "ID", "TestProperty.ID").ToList();
    

    Note:
    You can use similar approach to expand for OrderBy etc. - but this wasn't meant to cover all angles (or any real queries)

    Deep Property Expressions from this post of mine


    0 讨论(0)
提交回复
热议问题