【问题标题】:Converting List<string> to EntityFramework column/field list将 List<string> 转换为 EntityFramework 列/字段列表
【发布时间】:2013-04-10 09:53:31
【问题描述】:

使用 EntityFramework,我可以使用以下语法获取某种类型的实体列表:

List<Customer> customers = ((IQueryable<Customer>)myEntities.Customers
     .Where(c => c.Surname == strSurname)
     .OrderBy(c => c.Surname)).ToList<Customer>();

然后我可以这样做以只得到我感兴趣的数据:

var customerSummaries = from s in customers
     select new
     {
        s.Surname, s.FirstName, s.Address.Postcode
     };

我得到了包含所请求汇总数据的字段(以及必要时的表格)的strings 列表(基于用户选择)。例如,对于上面的“customerSummary”,提供的strings 列表将是:“Surname”、“FirstName”、“Address.Postcode”。

我的问题是:如何将该字符串列表转换为仅提取指定字段所需的语法?

如果无法做到这一点,那么对于列列表,什么类型(比字符串)更好,以便我可以提取正确的信息?

如果有意义的话,我想我需要知道 EF [entity|table] 的 [member|column|field] 的类型。

编辑:

我尝试了建议的答案 - 动态 linq - 使用以下语法

string parmList = "Surname, Firstname, Address.Postcode";
var customers = myEntities.Customers.Select(parmList)
  .OrderBy("Address.Postcode");

但这会导致:EntitySqlException was unhandled. 'Surname' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly.

所以,一个后续问题。我是否正确使用Select?我只看到使用WhereOrderBy 子句的示例,但我认为基于这些我做对了。

如果我的 Select 语法不是问题,谁能看到是什么问题?

编辑 2:它是颠倒的。这有效:

string parmList = "Surname, Firstname, Address.Postcode";
var customers = myEntities.Customers
  .OrderBy("Address.Postcode")
  .Select(parmList);

【问题讨论】:

  • 您可以使用其他方法吗?例如存储过程?它可能不是 linq,但如果它是一次性的,那么实现起来会非常简单。
  • 我曾考虑过使用直接 sql,如果/当我被击败时,我会尝试一下,但还不是现在。 :-)

标签: c# linq entity-framework


【解决方案1】:

您可以使用 dynamic linq,请在here 中查看。它也可以在nuget

【讨论】:

  • 感谢您的链接,您能看看我的编辑吗?
【解决方案2】:

我建议dynamic linq @Cuong 已经发布。

但是对于简单的Select 投影和表达式中的手工练习......

使用来自How to create LINQ Expression Tree to select an anonymous typeLinqRuntimeTypeBuilder
(请参阅那里的 cmets 以了解“为什么”是必要的)

然后添加这个...

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;
}

像这样使用它 例如:

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();

注意:
您可以使用类似的方法来扩展 OrderBy 等 - 但这并不意味着涵盖所有角度(或任何实际查询)

Deep Property Expressions 来自this post of mine


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    • 2015-07-29
    相关资源
    最近更新 更多