0

我是 EntityFramework 的新手,遇到了查询中使用的不受支持的函数的问题。因此,我希望社区可以帮助找到一种优雅的方式。
该查询尝试根据用户名和/或 Windows 用户名查找用户。

[Flags]
public enum IdentifierType
{
    Username = 1,
    Windows = 2,
    Any = Username | Windows,
}

以下代码引发NotSupportedException,因为 Enum.HasFlag 无法转换为存储表达式。

public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
    using (var context = contextFactory.Invoke())
    {
        var user = context.Users.FirstOrDefault(u => u.Username == identifier && type.HasFlag(IdentifierType.Username)
        || u.WindowsUsername == identifier && type.HasFlag(IdentifierType.Windows));

        return user;
    }
}

如果我以旧的方式重写查询,则查询有效,但布尔逻辑在数据库中执行:

public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
    using (var context = contextFactory.Invoke())
    {
        var user = context.Users.FirstOrDefault(u => u.Username == identifier && (type & IdentifierType.Username) == IdentifierType.Username
        || u.WindowsUsername == identifier && (type & IdentifierType.Windows) == IdentifierType.Windows);

        return user;
    }
}

WHERE ((Username = @username) AND (1 = (3 & (1)))) OR (WindowsUsername = @windowsusername) AND (2 = (3 & (2))))

如何强制框架在将布尔逻辑发送到数据库之前对其进行评估,因此二进制操作不在数据库级别完成?

任何想法都非常感谢!

4

3 回答 3

0

例如:

public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
    using (var context = contextFactory.Invoke())
    {
        IdentifierType tw = type & IdentifierType.Windows;
        IdentifierType tu = type & IdentifierType.Username;
        var user = context.Users.FirstOrDefault(u => u.Username == identifier && tu == IdentifierType.Username
        || u.WindowsUsername == identifier && tw == IdentifierType.Windows);

        return user;
    }
}

但我希望并相信数据库服务器检测到 1 = (3 & (1)) 是一个常数

于 2013-01-30T13:37:17.037 回答
0

给你(我已经将我的代码转换为你的,所以在语法上可能不是 100%)......

public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
    using (var context = contextFactory.Invoke())
    {
        var user = context.Users.FirstOrDefault(u => u.Username == ((type.HasFlag(IdentifierType.Username)) ? identifier : u.Username) && 
    && u.WindowsUsername == ((type.HasFlag(IdentifierType.Username)) ? identifier : u.WindowsUsername);

        return user;
    }
}
于 2013-01-30T14:06:05.147 回答
0

对不起,我意识到这个问题没有指出有效的问题。在阅读了更多相关内容之后,我不得不重写这个问题,最后从 Gert Arnold 那里得到了一个很好的答案,见这里

LINQKit提供了强大的扩展,如PredicateBuilder以涵盖具有 OR 条件的动态查询。

于 2013-01-31T10:20:57.763 回答