次のようなEF-Code First CTP5エンティティレイアウトを考えます。
_public class Person { ... }
_
次のコレクションがあります。
_public class Address { ... }
_
次の単一の関連付けがあります。
_public class Mailbox { ... }
_
私はやってみたいです:
PersonQuery.Include(x => x.Addresses).Include("Addresses.Mailbox")
マジックストリングを使用せずに。ラムダ式を使用してそれを行いたいです。
上記で入力した内容がコンパイルされ、検索条件に一致するすべてのPersonがそのアドレスと各アドレスのメールボックスが読み込まれていることを認識しますが、それは文字列であり、私を苛立たせます。
文字列なしでそれを行うにはどうすればよいですか?
おかげでスタック!
まだこれに対する解決策を探している人のために、LambdaインクルードはEF 4+の一部であり、System.Data.Entity名前空間にあります。ここの例
http://romiller.com/2010/07/14/ef-ctp4-tips-tricks-include-with-lambda/
この投稿で説明されています: http://www.thomaslevesque.com/2010/10/03/entity-framework-using-include-with-lambda-expressions/
編集(読みやすさのためにAskerによる):探している部分は以下のとおりです。
public static class ObjectQueryExtensions
{
public static ObjectQuery<T> Include<T>(this ObjectQuery<T> query, Expression<Func<T, object>> selector)
{
string path = new PropertyPathVisitor().GetPropertyPath(selector);
return query.Include(path);
}
class PropertyPathVisitor : ExpressionVisitor
{
private Stack<string> _stack;
public string GetPropertyPath(Expression expression)
{
_stack = new Stack<string>();
Visit(expression);
return _stack
.Aggregate(
new StringBuilder(),
(sb, name) =>
(sb.Length > 0 ? sb.Append(".") : sb).Append(name))
.ToString();
}
protected override Expression VisitMember(MemberExpression expression)
{
if (_stack != null)
_stack.Push(expression.Member.Name);
return base.VisitMember(expression);
}
protected override Expression VisitMethodCall(MethodCallExpression expression)
{
if (IsLinqOperator(expression.Method))
{
for (int i = 1; i < expression.Arguments.Count; i++)
{
Visit(expression.Arguments[i]);
}
Visit(expression.Arguments[0]);
return expression;
}
return base.VisitMethodCall(expression);
}
private static bool IsLinqOperator(MethodInfo method)
{
if (method.DeclaringType != typeof(Queryable) && method.DeclaringType != typeof(Enumerable))
return false;
return Attribute.GetCustomAttribute(method, typeof(ExtensionAttribute)) != null;
}
}
}