![](/img/trans.png)
[英]Creating a dynamic EF filter that builds a LINQ Where equals/contains statement for any string entity property
[英]Expression to get LINQ with Contains to EF for SQL IN() where on entities child's property equals value
我有一個簡單的需要,從返回的集合中過濾掉所有父項,其中字段上沒有匹配項,即從字符串中按名稱調用,與呈現的值不匹配。 我所追求的是,如果parent
對象具有child
對象,並且該child
對象屬性"foo"
(由字符串調用)不等於或等於值bar
,則從集合中適當地過濾parent
對象。
這是我的 linq ef 電話
var field = "bar";
var values = new List<string>{"foo","fuYu"};
var dataPage = _aim_context.ae_s_bld_c.AsNoTracking();
var result = dataPage.Where(x =>
DbHelper.byPropertyContains(x.udfs, field, values)
);
// NOTE `udfs` is a ONE-to-ONE with `ae_s_bld_c`
我希望看到的是類似於 SQL 的東西
SELECT [m].[id],[m.udfs].[bar],
FROM [dbo].[ae_s_bld_c] AS [m]
INNER JOIN [dbo].[ae_s_bld_c_udf] AS [m.udfs]
ON ([m].[multitenant_id] = [m.udfs].[multitenant_id])
WHERE ([m].[multitenant_id] = 1.0)
AND ([m.udfs].[bar] IN ('foo','fuYu')) --< Goal line
我處理這個問題的方法是設置一個表達式來獲取List<string>
並生成 SQL。 我已經閱讀了近 50 篇文章和 SO 帖子,但還沒有弄清楚為什么我還沒有得到這個,因為每個人似乎都有不同的想法,而且大多數似乎都不符合 dotnet core 2.1+。
這是我經過多次迭代后目前所坐的。 注意:它與我所追求的略有不同,因為我正在提供我目前的線索。
我當前的上下文 linq 嘗試
//...
dataPage = dataPage.Where(DbHelper.byPropertyContains<ae_s_bld_c>("udfs", field, values));
//...
我認為如果它像我提出的第一個例子會更好,但這就是我已經登陸的原因,因為我有時間將它與x=>x.udfs
,兩者都是x=> funName(x.udfs)
和x=> x.udfs.funName()
我構建表達式的靜態方法
public static class DbHelper
{
public static Expression<Func<T, bool>> byPropertyContains<T>(string node, string field, List<string> value) {
//trying to take parent item and get it's property by string name because
// doing the function in linq like x=>x.udfs was not working right
// but that is the prefered I think
var property_parameter = Expression.Parameter(typeof(T), "x");
var property = Expression.PropertyOrField(property_parameter, node);
var selector_parameter = Expression.Parameter(property.Type, "y");
var selector = Expression.PropertyOrField(selector_parameter, field);
var methodInfo = typeof(List<string>).GetMethod("Contains", new Type[] {
typeof(string)
});
var list = Expression.Constant(value, typeof(List<string>));
var body = Expression.Call(methodInfo, list, selector);
return Expression.Lambda<Func<T, bool>>(body, selector_parameter);
}
}
根據@NetMage 的要求,我嘗試使用 LINQpad 向后工作。 我想我很接近,但很難用輸出來判斷。 我把它放在這里以供參考。 需要明確的是,孩子的屬性名稱將是名稱的字符串。 最好的結果是我可以有一個像udfs.foo
這樣的名稱,如果值包含字符串名稱,我可以在任何級別上進行測試,但從這里開始真的沒問題,
var result = dataPage.Where(x =>
DbHelper.byPropertyContains(x.udfs, field, values)
);
讓我們從這里開始。 你需要一個類似這樣的東西
var result = dataPage.Where(x => values.Contains(x.udfs.{field}));
其中field
是一個字符串,返回由名稱動態指定的屬性。
在 EF Core 中,您甚至不需要手動處理構建表達式,因為 EF Core 提供了一個特殊的 SQL 可翻譯函數,用於通過名為EF.Property的名稱訪問簡單屬性。
使用該方法,解決方案很簡單:
var result = dataPage
.Where(x => values.Contains(EF.Property<string>(x.udfs, field)));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.