動的LINQで存在させるにはどうすればよいですか?
動的LINQを使用してSQL句を作成しようとしています。私は多くのことを調査しましたが、満足のいく答えは見つかりませんでした。
SQLクエリを次のように変換してみます。
select * from Documento where exists(
select 1 from Titulo
where Documento.codDocumento = Titulo.codDocumento
and Documento.codEmpresa = Titulo.codEmpresaDocumento
and Titulo.codFluxoConta = 'SomeValue'
and Titulo.codEmpresaFluxoConta = 'StringNumerical')
一般的なLINQでは、次のようにしました。
var subquery2 = from T in db.Titulos
where T.codFluxoConta == "SomeValue"
&& T.codEmpresaFluxoConta == "StringNumerical"
select new {
codDoc = (int?)T.codDocumento,
codEmp = (string)T.codEmpresaDocumento
};
var query2 = from D in db.Documentos
where subquery2.Contains(new { codDoc = (int?)D.codDocumento, codEmp = (string)D.codEmpresa })
select new{
D.codDocumento,
D.codEmpresa
};
または
var query4 = db.Documentos.Where(d =>
(db.Titulos.Where(t => t.codFluxoConta == "SomeValue" && t.codEmpresaFluxoConta == "StringNumerical").Select(t2 => new { codDoc = (int?)t2.codDocumento, codEmp = (string)t2.codEmpresaDocumento })).Contains(new { codDoc = (int?)d.codDocumento, codEmp = (string)d.codEmpresa }));
そして、これは私が私の知識でやったことです
IQueryable linq = db.Set(T);
var exists = linq.Where("codFluxoConta == @0 && codEmpresaFluxoConta == @1", "SomeValue", "StringNumerical").Select("new(\"codDocumento\" as codDoc, \"codEmpresaDocumento\" as codEmp)");
var query = db.Documentos.Where("@0.Contains(new (it[\"codDocumento\"] as codDocumento, it[\"codEmpresa\"] as codEmpresaDocumento))", exists);
しかし、このコードを実行すると、次の例外が発生します。
タイプ 'DynamicClass3'に該当するインデクサーはありません。
これは動作するようです... outerIt
使用しouterIt
...そしてWhere()
内のAny
どの魔法を介して動作するのかわかりません...
var sq = titulo.Where("codFluxoConta == @0 && codEmpresaFluxoConta == @1", "SomeValue", "StringNumerical");
var result = documento.Where("@0.Any(it.codDocumento == outerIt.codDocumento && it.codEmpresaDocumento == outerIt.codEmpresaDocumento)", sq)
.Select("new(codDocumento, codEmpresaDocumento)");
Where()
it
ながら、サブクエリの要素であるouterIt
あるdocumento
。
SQLプロファイラーで確認したところ、クエリの結果は次のとおりです。
SELECT
[Extent1].[codDocumento] AS [codDocumento],
[Extent1].[codEmpresaDocumento] AS [codEmpresaDocumento]
FROM [dbo].[Documento] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Titulo] AS [Extent2]
WHERE (N'SomeValue' = [Extent2].[codFluxoConta]) AND (N'StringNumerical' = [Extent2].[codEmpresaFluxoConta]) AND ([Extent2].[codDocumento] = [Extent1].[codDocumento]) AND ([Extent2].[codEmpresaDocumento] = [Extent1].[codEmpresaDocumento])
)
これはクエリと同等です。
動的なLINQの中で使用して、あなたがLINQの中で書いたものに非常に類似したクエリを記述することも可能であることに注意してください.Contains()
私は好むんのでご注意.Any()
に.Contains()
2つのクエリは、Entity Frameworkを使用して同じSQLクエリを生成します。
var sq2 = db.Titulo.Where("codFluxoConta == @0 && codEmpresaFluxoConta == @1", "SomeValue", "StringNumerical")
.Select("new(codDocumento, codEmpresaDocumento)");
var result2 = db.Documento.Where("@0.Contains(new(outerIt.codDocumento, outerIt.codEmpresaDocumento))", sq2)
.Select("new(codDocumento as codDoc, codEmpresaDocumento as codEmp)");
Any()( https://msdn.microsoft.com/en-us/library/vstudio/bb534972%28v=vs.100%29.aspx )は、おそらく焦点を当てるべきものです。 Any()は、指定された述語を満たすコレクション内に少なくとも1つのアイテムが見つかった場合にTrueを返します。
これをテストするVSはありませんが、これでうまくいくはずです。
db.Documento.Where(d =>
db.Titulos.Any(t =>
t.codDocumento == d.codDocumento &&
t.codEmpresaDocumento == d.codEmpresa &&
t.codFluxoConta == "" &&
t.codEmpresaFloxoConta == ""
)
);
変数を使用してcodFluxoContaおよびcodEmpresaFloxoContaと比較する可能性が高いため、クエリ( http://blogs.msdn.com/b/charlie/archive/2007)を実行するまでステートメントの値を読み取らないことに注意してください。 /12/09/deferred-execution.aspx )。したがって、これを(ループのように)異なる値で実行して結果を保存する場合は、値が変更される前に、必ず.ToList()または何かの結果を取得してください。