私は式ツリーにやや慣れていないので、いくつかのことをよく理解していません。
私がする必要があるのは、値のリストを送信し、それらの値からエンティティの列を選択することです。したがって、次のような呼び出しを行います。
DATASTORE<Contact> dst = new DATASTORE<Contact>();//DATASTORE is implemented below.
List<string> lColumns = new List<string>() { "ID", "NAME" };//List of columns
dst.SelectColumns(lColumns);//Selection Command
これを次のようなコードに変換したい (Contact
は EF4 を使用するエンティティです):
Contact.Select(i => new Contact { ID = i.ID, NAME = i.NAME });
だから、私は次のコードを持っているとしましょう:
public Class<t> DATASTORE where t : EntityObject
{
public Expression<Func<t, t>> SelectColumns(List<string> columns)
{
ParameterExpression i = Expression.Parameter(typeof(t), "i");
List<MemberBinding> bindings = new List<MemberBinding>();
foreach (PropertyInfo propinfo in typeof(t).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (columns.Contains(propinfo.Name))
{
MemberBinding binding = Expression.Bind(propinfo, Expression.Property(i, propinfo.Name));
bindings.Add(binding);
}
}
Expression expMemberInit = Expression.MemberInit(Expression.New(typeof(t)), bindings);
return Expression.Lambda<Func<t, t>>(expMemberInit, i);
}
上記のコードを実行すると、次のエラーが発生しました。
エンティティまたは複合型 'Contact' は、LINQ to Entities クエリでは作成できません。
クエリの本文を確認したところ、次のコードが出力されました。
{i => new Contact() {ID = i.ID, NAME = i.NAME}}
これができるかどうかを確認するためのテストとしてこの行を明示的に書いたので、新しいエンティティを構築できるはずだと確信しています。
.Select(i => new Contact{ ID = i.ID, NAME = i.NAME })
これは機能しましたが、選択を動的に構築する必要があります。
単純なクエリを逆コンパイルしようとしましたが (低レベルのコードを初めて見たとき)、完全に翻訳できません。私が入力した高レベルのコードは次のとおりです。
Expression<Func<Contact, Contact>> expression = z =>
new Contact { ID = z.ID, NAME = z.NAME };
逆コンパイラで使用されるフレームワークを変更すると、次のコードが得られます。
ParameterExpression expression2;
Expression<Func<Contact, Contact>> expression =
Expression.Lambda<Func<Contact, Contact>>
(Expression.MemberInit(Expression.New((ConstructorInfo) methodof(Contact..ctor),
new Expression[0]), new MemberBinding[] { Expression.Bind((MethodInfo)
methodof(Contact.set_ID), Expression.Property(expression2 = Expression.Parameter(typeof(Contact), "z"), (MethodInfo)
methodof(Contact.get_ID))), Expression.Bind((MethodInfo)
methodof(Contact.set_NAME), Expression.Property(expression2, (MethodInfo)
methodof(Contact.get_NAME))) }), new ParameterExpression[] { expression2
});
これを理解するためにいくつかの場所を見てきましたが、まだ完全には理解できていません。誰でも助けることができますか?
これらは私が見たいくつかの場所です:
- msdn ブログ-- これはまさに私がやりたいことですが、デコピーしたコードには Expression.Call がありません。
- msdn MemberInit
- msdn 式のプロパティ
- stackoverflow EF は特定の列のみを取得します- これは近いですが、クエリの選択を使用するのと同じことをしているようです。
- 選択クエリで使用されるstackoverflowラムダ式-ここでの答えはまさに私がやりたいことです。逆コンパイルされたコードをC#に変換する方法がわかりません。