我想为我的List Collection应用动态项目。用户将选择注释的列,但列表的属性。我想从LINQ语句中获取列的子集。我想使用Dynamic LINQ。 any1可以提供如何使用表达式树实现项目。我想在Azure表存储上应用动态投影..
我尝试实现下面的代码,它不起作用,它在读取属性时抛出异常:
属性XXXX未定义类型'System.String'
代码:
DataMovementDataContext dbMovement = new DataMovementDataContext();
var entity = dbMovement.ListofAccountingDocs2_1075s.AsQueryable();
Type type = entity.ElementType;
var entityParam = Expression.Parameter(entity.ElementType, "row");
Expression expr = entityParam;
string[] props = "AccountingDocumentNbr,GLCompanyCode,DocumentFiscalYearNbr".Split(',');
var epr = GenerateMemberExpression<ListofAccountingDocs2_1075, string>("Name");
foreach (string prop in props)
{
// use reflection (not ComponentModel) to mirror LINQ
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
// type = pi.PropertyType; //Property 'System.String GLCompanyCode' is not defined for type 'System.String'
}
// row => row.Property
// var columnLambda = Expression.Lambda( Expression.Property(entityParam, "GLCompanyCode"), entityParam);
var columnLambda = Expression.Lambda(Expression.Property(expr, "AccountingDocumentNbr,GLCompanyCode"), entityParam);
// Items.Select(row => row.Property)
var selectCall = Expression.Call(typeof(Queryable), "Select", new Type[] { entity.ElementType, columnLambda.Body.Type }, entity.Expression, columnLambda);
// Items.Select(row => row.Property).Distinct
var distinctCall = Expression.Call(typeof(Queryable), "Distinct", new Type[] { typeof(string) }, selectCall);
// colvalue => colvalue
var sortParam = Expression.Parameter(typeof(string), "AccountingDocumentNbr");
var columnResultLambda = Expression.Lambda(sortParam, sortParam);
// Items.Select(row => row.Property).Distinct.OrderBy(colvalue => colvalue)
var ordercall = Expression.Call(typeof(Queryable), "OrderBy",
new Type[] { typeof(string), columnResultLambda.Body.Type },
distinctCall, columnResultLambda);
var result = entity.Provider.CreateQuery(ordercall);
foreach (var item in result)
{
Console.Write(item);
}
答案 0 :(得分:3)
如果您发布了正在使用的模型的类定义,那将会更容易。
但是,看起来您正试图通过链接来获取多个属性。这不起作用。我想你想要的是:
new {
AccountingDocumentNbr = document.AccountingDocumentNbr,
GLCompanyCode = document.GLCompanyCode ,
DocumentFiscalYearNbr = document.DocumentFiscalYearNbr
};
但foreach (string prop in props)
循环实际上是您需要的东西:
document.AccountingDocumentNbr.GLCompanyCode.DocumentFiscalYearNbr
现在,document.AccountingDocumentNbr
似乎是string
,因为您收到Property 'System.String GLCompanyCode' is not defined for type 'System.String'
错误。当你这样看时,错误是有道理的...... System.String
没有GLCompanyCode
属性,你正在构建一个链式属性表达式,期望它有一个。还会发生什么?
除非您的解决方案中已存在该类型的实例,否则您无法获取它所针对的匿名对象。这是因为匿名类型不是动态类型。它们可能看起来像它,但它们实际上是internal types compiled into the assembly,并且它们的功能与具有相同成员和Equals(object obj)
,GetHashCode()
和{的自定义覆盖的任何其他类的功能完全不同。 {1}}。因此,除非您有方法使用您要查找的定义引用类,否则您将无法使用反射访问这些成员(因为它们不存在)。使用lambda表达式会好得多。
为了更加清晰一点,以下是上面匿名类型的类定义(几乎就是这样)。
ToString()
答案 1 :(得分:0)
我能够解决我的问题。
public static Expression<Func<ListofAccountingDocs2_1075, ListofAccountingDocs2_1075>> BuildExpression(string parameters)
{
dynamic test = new ExpandoObject();
var sourceMembers = typeof(ListofAccountingDocs2_1075).GetProperties();
string[] selectparams = parameters.Split(',');//property names are comma seperated
foreach (var item in selectparams)
{
((IDictionary<string, object>)test).Add(item,string.Empty);
}
IDictionary<string,object> test2 = new Dictionary<string,object>();
List<PropertyInfo> destinationProperties = new List<PropertyInfo>();
foreach (var item in ((IDictionary<string, object>)test))
{
var selectedColumn = typeof(ListofAccountingDocs2_1075).GetProperties().FirstOrDefault(k =>
k.Name.Equals(item.Key));
if (selectedColumn != null)
destinationProperties.Add(selectedColumn);
}
var name = "src";
var parameterExpression = Expression.Parameter(typeof(ListofAccountingDocs2_1075), name);
return Expression.Lambda<Func<ListofAccountingDocs2_1075, ListofAccountingDocs2_1075>>(
Expression.MemberInit(
Expression.New(typeof(ListofAccountingDocs2_1075)),
destinationProperties.Select(k => Expression.Bind(k,
Expression.Property(
parameterExpression, k.Name)
)
).ToArray()
),
parameterExpression
);
}