LINQ 表达式中的函数应用

发布于 2024-11-10 12:31:42 字数 1188 浏览 3 评论 0原文

我们正在尝试找到解决实体框架不支持非标量实体问题的解决方法。我们正在使用特定的等式,因此我们尝试构建一个表达式,对于给定的输入和该输入的函数检查该等式是否成立。

    private static Expression<Func<TElement, bool>> UserEquals<TElement>(User user, Func<TElement, User> select)
    {
        var userequals = (Expression<Func<User, Boolean>>) (u => u.Source == user.Source && u.UserName == user.UserName);

        //return an Expression that receives an TElement, applies |select| and then passes that result to then `userequals` expression 
        // and uses it's result as return value.
    }

我怀疑它涉及创建一个接收参数的新表达式,但我无法弄清楚如何将 select 函数应用于该输入,然后将其结果传递给 userequals表达式。

预期用法类似于:

Context.Foo.Where(UserEquals(user, (f => f.User)).Single(f => f.Id == id);

而不是:

Context.Foo.Single(f => f.Id == id && f.User.Source == user.Source && f.User.UserName == user.UserName);

理想情况下,我们希望编写如下内容:

Context.Foo.Single(f => f.Id == id && f.User.Equals(user))
// or
Context.Foo.Single(f => f.Id == id && f.User == user)

We are trying to find a workaround for the issue that the Entity Framework doesn't support non-scalar entities. We are using a particular equality so we try to build an expression that for a given input and a function from that input checks whether that equality holds.

    private static Expression<Func<TElement, bool>> UserEquals<TElement>(User user, Func<TElement, User> select)
    {
        var userequals = (Expression<Func<User, Boolean>>) (u => u.Source == user.Source && u.UserName == user.UserName);

        //return an Expression that receives an TElement, applies |select| and then passes that result to then `userequals` expression 
        // and uses it's result as return value.
    }

I suspect it involves creating a new expression that receives a parameter, but I cannot figure out how to apply the select function to that input and then pass the result of that on to the userequals expression.

The intended usage is something like:

Context.Foo.Where(UserEquals(user, (f => f.User)).Single(f => f.Id == id);

Instead of:

Context.Foo.Single(f => f.Id == id && f.User.Source == user.Source && f.User.UserName == user.UserName);

Ideally we would want to write something like:

Context.Foo.Single(f => f.Id == id && f.User.Equals(user))
// or
Context.Foo.Single(f => f.Id == id && f.User == user)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

永言不败 2024-11-17 12:31:42

因此,如果我理解正确,您需要这样做:

public class Foo
{
    public int Id { get; set; }
    public User User { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Text { get; set; }
}

public static IQueryable<Foo> WhereUserEquals(this IQueryable<Foo> source, User user)
{
    // this is your implementation of the entity specific equality test
    return source.Where(x => x.User.Id == user.Id);
}

static void Main(string[] args)
{
    var list = new List<Foo> { new Foo { User = new User { Id = 1, Text = "User" } };

    var user = new User { Id = 1 };

    var q = list.AsQueryable().WhereUserEquals(user);

    foreach (var item in q)
    {
        Console.WriteLine(item.Text);
    }
}

这将允许您编写:

Context.Foo.WhereUserEquals(user).Single(f => f.Id == id);

如果您没有用于访问 Foo 类型的 User 属性的基类,则每种类型都需要一个这样的扩展,但是,这是你可以很容易地编写 gen 代码的东西。我认为没有必要重写表达式树。

So, if I'm understanding you correctly you want to do this:

public class Foo
{
    public int Id { get; set; }
    public User User { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Text { get; set; }
}

public static IQueryable<Foo> WhereUserEquals(this IQueryable<Foo> source, User user)
{
    // this is your implementation of the entity specific equality test
    return source.Where(x => x.User.Id == user.Id);
}

static void Main(string[] args)
{
    var list = new List<Foo> { new Foo { User = new User { Id = 1, Text = "User" } };

    var user = new User { Id = 1 };

    var q = list.AsQueryable().WhereUserEquals(user);

    foreach (var item in q)
    {
        Console.WriteLine(item.Text);
    }
}

Which would allow you to write:

Context.Foo.WhereUserEquals(user).Single(f => f.Id == id);

If you don't have a base class for accessing the User property of the type Foo you need one such extension for each type, however, that's something which you could quite easily code gen. I don't believe expression tree rewriting will be necessary.

农村范ル 2024-11-17 12:31:42

您是否有机会寻找 调用表达式?

Are you by any chance looking for InvokeExpression?

岛徒 2024-11-17 12:31:42

这行得通吗?

private static Expression<Func<TElement, bool>> UserEquals<TElement>(User user, Expression<Func<TElement, User>> select)
{
    return (Expression<Func<TElement, Boolean>>)(elt => select.Compile()(elt).Source == user.Source && select.Compile()(elt).UserName == user.UserName);
}

目前,您的类型不匹配,因为 select 未在任何地方调用,因此您没有 TElement 作为输入,但已经是 User

希望这有帮助...

Could this work ?

private static Expression<Func<TElement, bool>> UserEquals<TElement>(User user, Expression<Func<TElement, User>> select)
{
    return (Expression<Func<TElement, Boolean>>)(elt => select.Compile()(elt).Source == user.Source && select.Compile()(elt).UserName == user.UserName);
}

Currently you have a type mismatch since select is invoked nowhere, and thus you have not a TElement as input but already an User.

Hope this helps...

陌路终见情 2024-11-17 12:31:42

该库解决了该问题: http://nuget.org/List/Packages/Microsoft.Linq .翻译

在这里阅读更多相关信息:http://damieng.com/blog/2009/06/24/client-side-properties-and-any-remote-linq-provider

我在生产中严重依赖于此。

This library solves the problem: http://nuget.org/List/Packages/Microsoft.Linq.Translations

Read more about it here: http://damieng.com/blog/2009/06/24/client-side-properties-and-any-remote-linq-provider

I'm relying heavily on this in production.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文