2013-04-10 58 views
3

使用的EntityFramework,我可以使用下面的語法某種類型的實體名單:轉換列表<string>到的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 
    }; 

我給出的領域string S(基於用戶選擇)列表,包括請求的彙總數據(表和在必要時)。例如,對於上述「customerSummary」,提供的string列表將是:「姓氏」,「名字」,「地址。郵編」。

我的問題是:如何將該字符串列表轉換爲僅提取指定字段所需的語法?

如果不能這樣做,列的列表會是什麼樣的更好的類型(比字符串),所以我可以提取正確的信息?

我想我需要知道EF [實體|表]的[成員|列|字段]的類型,如果有意義的話。

編輯:

我嘗試了建議答案 - 動態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子句的例子,但我認爲我正是基於這些做的。

如果我的選擇語法不是問題,任何人都可以看到是什麼?

編輯2:它是顛倒的。這工作:

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

有沒有其他方法可以使用?例如一個存儲過程?它可能不是linq,但如果它是一次性的事情,它將非常簡單。 – lahsrah 2013-04-10 10:24:44

+0

我想過使用直接的sql,如果/當我被毆打時,我會試一試,但不只是。 :-) – mcalex 2013-04-10 15:21:00

回答

2

您可以使用動態LINQ,檢查它在here。它也可在nuget

+0

感謝您的鏈接,你可能看看我的編輯? – mcalex 2013-04-11 07:58:49

2

我建議dynamic linq作爲@Cuong已發佈。

但對於簡單Select預測和作爲表達式中的手工製作的運動...

使用LinqRuntimeTypeBuilderHow to create LINQ Expression Tree to select an anonymous type
(見註釋那裏「爲什麼」是必要的)

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

使用它就像

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

注:
您可以使用類似的方法來擴大排序依據等等 - 但是這並不意味着覆蓋所有角(或任何真正的查詢)

Deep Property Expressionsthis post of mine