[英]Left outer join with Linq Expressions
I'm trying to build left outer join queries with Linq Expressions but now I really hit the wall. 我正在尝试使用Linq Expressions建立左外部联接查询,但现在我真的很困难。
What I want to accomplish is the following query: 我要完成的是以下查询:
var q =
from i in ProcessInstances
join dof1 in Queries.DataObjectFieldsQuery(this) on new { instanceId = i.ObjectID, dataId = fields[0,0], fieldId = fields[0,1] } equals new { instanceId = dof1.ProcessInstanceObjectID, dataId = dof1.DataID, fieldId = dof1.FieldID } into dofs1
from dof1 in dofs1.DefaultIfEmpty()
join dof2 in Queries.DataObjectFieldsQuery(this) on new { instanceId = i.ObjectID, dataId = fields[1,0], fieldId = fields[1,1] } equals new { instanceId = dof2.ProcessInstanceObjectID, dataId = dof2.DataID, fieldId = dof2.FieldID } into dofs2
from dof2 in dofs2.DefaultIfEmpty()
join dof3 in Queries.DataObjectFieldsQuery(this) on new { instanceId = i.ObjectID, dataId = fields[2,0], fieldId = fields[2,1] } equals new { instanceId = dof3.ProcessInstanceObjectID, dataId = dof3.DataID, fieldId = dof3.FieldID } into dofs3
from dof3 in dofs3.DefaultIfEmpty()
select new WorkitemListModel
{
InstanceId = i.ObjectID,
FormFieldValue1 = dof1.FieldValue,
FormFieldValue2 = dof2.FieldValue,
FormFieldValue3 = dof3.FieldValue,
};
I have defined the following classes: 我定义了以下类:
public class WorkitemListModel
{
public string InstanceId { get; set; }
public string FormFieldValue1 { get; set; }
public string FormFieldValue2 { get; set; }
public string FormFieldValue3 { get; set; }
}
public class DataObjectField
{
public string ProcessInstanceObjectID { get; set; }
public string DataID { get; set; }
public string FieldID { get; set; }
public string FieldValue { get; set; }
}
public class ModelWithFields<TModel>
{
public IEnumerable<DataObjectField> DataObjectFields { get; set; }
public TModel Model { get; set; }
}
public class OuterKeySelector
{
public string instanceId { get; set; }
public string dataId { get; set; }
public string fieldId { get; set; }
}
I created the GroupJoin expression wich gives no compile errors. 我创建的GroupJoin表达式不产生编译错误。 (I left out som code here):
(我在这里省略了som代码):
var q = dc.Instances;
System.Type modelType = typeof(ModelWithFields<>);
System.Type outerKeyType = typeof(WorkitemListModel);
System.Type resultType = modelType.MakeGenericType(outerKeyType);
//... MemberInitExpression and Expression.Bind
q = q.Provider.CreateQuery(
Expression.Call(
typeof(Queryable),
"GroupJoin",
new[]
{
typeof(WorkitemListModel),
typeof(DataObjectField),
typeof(OuterKeySelector),
resultType,
},
query.Expression,
Expression.Constant(Queries.DataObjectFieldsQuery(dc)),
Expression.Quote(outerLambda),
Expression.Quote((Expression<Func<DataObjectField,OuterKeySelector>>)(
(DataObjectField dof) =>
new OuterKeySelector
{
instanceId = dof.ProcessInstanceObjectID,
dataId = dof.DataID,
fieldId = dof.FieldID
})),
Expression.Quote(resultLambda)));
// selectmany expression
// collectionSelector lambda -- temp.DataObjectFields.DefaultIfEmpty()
ParameterExpression collectionParameter = Expression.Parameter(resultType, "temp");
// This throw an exception
MethodCallExpression collectionCallExpression =
Expression.Call(
typeof(Queryable),
"DefaultIfEmpty",
new System.Type[]
{
typeof(IQueryable<>).MakeGenericType(typeof(DataObjectField))
},
Expression.Property(collectionParameter, resultType.GetProperty("DataObjectFields")));
But in the SelectMany method I'm trying to add DefaultIfEmpty but I get an exception saying: 但是在SelectMany方法中,我试图添加DefaultIfEmpty,但出现异常:
No generic method 'DefaultIfEmpty' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments.
类型'System.Linq.Queryable'的通用方法'DefaultIfEmpty'与提供的类型实参和实参不兼容。 No type arguments should be provided if the method is non-generic.
如果方法是非泛型的,则不应该提供任何类型参数。
I've tried the switched the typeparams from IQueryable to IEnumerable and event tried to call Enumerable.DefaultIfEmpty with no luck. 我试过将typeparams从IQueryable切换到IEnumerable,并且事件尝试调用Enumerable.DefaultIfEmpty,但是没有运气。 Perhaps it's something wrong with the PropertyExpression?
也许PropertyExpression出问题了?
I prefer a different overload for Expression.Call using MethodInfo
, here is a simple example I have working. 我更喜欢使用
MethodInfo
为Expression.Call使用不同的重载,这是我正在使用的简单示例。
Expression constant = Expression.Constant(new string[] { "a", "b" });
MethodInfo methodInfo = typeof(Enumerable).GetMethods().FirstOrDefault(c => (c as MethodInfo).Name == "DefaultIfEmpty");
methodInfo = methodInfo.MakeGenericMethod(typeof(string));
MethodCallExpression methodExpression = Expression.Call(methodInfo, constant);
I had defined incorrect type parameter of the Expression.Call method. 我定义了Expression.Call方法的错误类型参数。 It wasn't
IQueryable<DataObjectField>
but only DataObjectField
. 不是
IQueryable<DataObjectField>
,只有DataObjectField
。 This is what fixed it. 这就是修复它的原因。
MethodCallExpression collectionCallExpression =
Expression.Call(
typeof(Enumerable),
"DefaultIfEmpty",
new System.Type[]
{
typeof(DataObjectField)
},
Expression.Property(collectionParameter, newResultType.GetProperty("DataObjectFields"))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.