在EF 6.1中,已創建了一個DefaultExpressionVisitor以與IDbCommandTreeInterceptor配合使用。我想知道如何正確覆蓋DbJoinExpression訪問者以過濾連接的右側,然後執行相同的連接,但在過濾的集合上。如何過濾DbJoinExpression的一側
基於各種方法(如使用BindAs等),我得到的錯誤,如:
- 名爲「Extent2」無屬性由類型
- 的引用變量「Extent2」聲明是未在當前範圍內定義。
但我無法獲得可比類型,變量和參數的組合。他們的文檔很少,也沒有DbJoinExpressions在這種情況下使用的示例。
舉個例子說我有一個ObjectContext與人物和動物。 而且一個人與他們擁有的動物有一個關聯,而一個寵物擁有一個OwnerId。所以明確的Key關係在Person.Id == Animal.OwnerId之間。
我已經添加了一個關聯,也是一個導航屬性,並稱之爲「貓」。因此,爲了準確,我想使用AnimalType列作爲鑑別器過濾動物集合(右手錶達式)。
public override DbExpression Visit(DbJoinExpression expression)
{
//TODO pull these values from attributes etc
var discriminatorColumn = "AnimalType";
var discriminatorType = "Cat";
//People
DbExpressionBinding left = this.VisitExpressionBinding(expression.Left);
//Unfiltered Animals
DbExpressionBinding right = this.VisitExpressionBinding(expression.Right);
//TODO Filter the right side using the AnimalType dbcolumn and re-join
// Get the right hand collection element
var entitySetExpression = right.Expression as DbScanExpression;
var variableReference = right.Variable;
// Create the property based on the variable in order to apply the equality
var discriminatorProperty = DbExpressionBuilder.Property(variableReference, discriminatorColumn);
var predicateExpression = DbExpressionBuilder.Equal(discriminatorProperty, DbExpression.FromString(discriminatorType));
//Filtered Animals being Cats
var filterExpression = DbExpressionBuilder.Filter(entitySetExpression.Bind(),predicateExpression);
var joinCondition = this.VisitExpression(expression.JoinCondition) as DbComparisonExpression;
DbExpressionBinding filteredRight = filterExpression.Bind();
DbExpression newExpression = expression;
if (!ReferenceEquals(expression.Left, left)
|| !ReferenceEquals(expression.Right, filteredRight)
|| !ReferenceEquals(expression.JoinCondition, joinCondition))
{
if (DbExpressionKind.InnerJoin == expression.ExpressionKind)
{
newExpression = DbExpressionBuilder.InnerJoin(left, filteredRight, joinCondition);
}
else if (DbExpressionKind.LeftOuterJoin == expression.ExpressionKind)
{
newExpression = DbExpressionBuilder.LeftOuterJoin(left, filteredRight, joinCondition);
}
else
{
Debug.Assert(
expression.ExpressionKind == DbExpressionKind.FullOuterJoin,
"DbJoinExpression had ExpressionKind other than InnerJoin, LeftOuterJoin or FullOuterJoin?");
newExpression = DbExpressionBuilder.FullOuterJoin(left, filteredRight, joinCondition);
}
}
return newExpression;
}
從本質上講,我希望創建額外的過濾器有點像SQL連接:
SELECT ....
FROM People p LEFT JOIN
Animals a ON p.Id = a.OwnerId (here ***AND a.AnimalType = 'Cat'***)
WHERE (or here ***a.AnimalType = 'Cat'***)
讀source code on codeplex它是推動範圍變量DefaultExpressionVisitor但這種方法是私有的。這可能解釋我看到的參數範圍問題。
任何幫助,將不勝感激。
我有類似的問題。也許我的回答可以幫助你:http://stackoverflow.com/a/34187228/1876903, – Killo 2015-12-09 19:25:27