簡體   English   中英

Linq表達式選擇字段

[英]Linq Expression to Select a Field

我有一個非常具體的LINQ查詢。 我想檢查表中是否存在隨機生成的密鑰。

標准查詢可以定義為Select * from Products where SaleId == 'XXXXXXX' 在此查詢中,XXXXXX由隨機字符生成器生成(還提供了長度)。 我創建了以下LINQ擴展:

public static string GetUniqueId<T, TProperty>(this IEnumerable<T> source, int length, Func<T, TProperty> idProperty)
{
    bool isUnique = false;
    string uniqueId = String.Empty;
    while (!isUnique)
    {
        uniqueId = PasswordGenerator.GenerateNoSpecialCharacters(length);
        if (!String.IsNullOrEmpty(uniqueId))
        {
            isUnique = source.AsQueryable().SingleOrDefault(i => idProperty(i).Equals(uniqueId)) == null;
        }
    }
    return uniqueId;
}

但是,我注意到此方法首先選擇表中作為源傳遞的所有記錄,然后運行Where子句。 這種行為顯然非常耗時。 所以基本上它是SELECT * FROM Products然后運行SingleOrDefault

有沒有什么方法可以直接運行查詢,以便它從產品中選擇* * WHERE Id ='XXXXXXX'

這是我如何稱呼它的一個例子:

string id = c.L2SOnlineCountMasters.GetUniqueId(9, x => x.MID);

在這種情況下,L2SOnlineCountMasters是數據庫中的表,c是DataContext實例。

希望得到這個答案!

Cheerz,Anup

LINQ-to-SQL引擎無法知道Func<T, TProperty>作用。

您需要接受Expression<Func<T, TProperty>> ,然后將表達式拼接成一個調用.Equals的表達式。
代碼看起來像

Expression.Lambda<Func<T, TProperty>>(
    Expression.Call(idProperty.Body, "Equals", new Type[0], 
                    Expresion.Constant(uniqueId)),
    idProperty.Parameters
)

此外,您應該更改您的方法以獲取IQueryable<T>

在閱讀了這兩條評論之后,我意識到應該使用IQueryable。 但是,Expression Call中的“Equals”不起作用,因為它會拋出以下錯誤:“類型'System.String'上的多個方法'Equals'與提供的參數兼容。” 因此我修改了一下代碼如下:

public static string GetUniqueId<T, TProperty>(this IQueryable<T> source, int length, Expression<Func<T, TProperty>> idProperty)
    {
        bool isUnique = false;
        string uniqueId = String.Empty;
        while (!isUnique)
        {
            uniqueId = PasswordGenerator.GenerateNoSpecialCharacters(length);
            if (!String.IsNullOrEmpty(uniqueId))
            {
                var expr = Expression.Lambda<Func<T, bool>>(
                    Expression.Call(idProperty.Body, typeof(string).GetMethod("Equals", new[] { typeof(string) }), Expression.Constant(uniqueId)), idProperty.Parameters);
                isUnique = source.SingleOrDefault(expr) == null;
            }
        }

        return uniqueId;
    }

這真的解決了這個問題。

實際上,如果您調用c.L2SOnlineCountMaster轉換為IEnumerable,將檢索所有記錄,如果您嘗試這樣做:

    public static string GetUniqueId<T, TProperty>(this IQueryable<T> source, int length, Func<T, TProperty> idProperty)
{         
bool isUnique = false;         
string uniqueId = String.Empty;         
while (!isUnique) 
{             
uniqueId = PasswordGenerator.GenerateNoSpecialCharacters(length);             
if (!String.IsNullOrEmpty(uniqueId)) 
{ 
isUnique = source.SingleOrDefault(i => idProperty(i).Equals(uniqueId)) == null;
}
}
return uniqueId;
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM