简体   繁体   English

将C#函数移动到表达式以在Entity Framework / SQL Select中使用

[英]Moving C# function to expression for use in Entity Framework / SQL Select

I have some small C# functions and computed cols from views that I'd like to move to Expressions so that they execute directly against the datasource in native T/SQL. 我有一些小的C#函数和来自视图的计算cols,我想转移到Expressions,以便它们直接针对本机T / SQL中的数据源执行。

I can do this inline in the Select, but I'd like to move it to a common function for re-use and testing. 我可以在Select中内联这个,但是我想把它移到一个常用的函数来重复使用和测试。

var results = context
    .Products
    .Select(p => new StockDto
    {
        Stock = p.GoodStock - p.LiveStock // Real version is more complex.
    });

I've tried creating a function that returns an expression but C# attempts to assign the expression instead of the result of the expression and won't compile. 我已经尝试创建一个返回表达式的函数,但C#尝试分配表达式而不是表达式的结果,并且不会编译。 Using the following Expression variable does not compile either. 使用以下Expression变量也不编译。

public static readonly Expression<Func<DataModel.Product, int>> StockLevel = 
    expr => expr.GoodStock - 10;

I'm familiar with using expressions for appending to Where clauses but I can't figure out how to create an Expression that returns a string from a select statement. 我熟悉使用表达式附加到Where子句但我无法弄清楚如何创建一个从select语句返回一个字符串的Expression。

I'd like to do this; 我想这样做;

var results = context
    .Products
    .Select(p => new StockDto
    {
        Stock = StockExpression // StockExpression is written in C#
    });

LinqKit seems to be about making predicates (Where clauses) easier to work with, I can't see how to compile an Expression Tree. LinqKit似乎是关于使谓词(Where子句)更容易使用,我无法看到如何编译表达式树。 Is the only way to do this to code a complex expression tree by hand (I'd like to avoid that as it obscures the meaning of the code)? 是唯一的方法来手动编写复杂的表达式树(我想避免这样做,因为它模糊了代码的含义)?

LinqKit should work for you. LinqKit应该适合你。 You should call Invoke to use one expression in another. 您应该调用Invoke以在另一个中使用一个表达式。

You have two options for "expanding" the merged expressions: 您有两个“扩展”合并表达式的选项:

You either invoke AsExpandable on the IQueryable so that it "expands" expressions automatically like this: 您可以在IQueryable上调用AsExpandable ,以便它自动“扩展”表达式,如下所示:

var results = context
    .Products
    .AsExpandable()
    .Select(p => new StockDto
    {
        Stock = StockLevel.Invoke(p) 
    });

Or you expand the expression manually before using it like this: 或者在使用之前手动展开表达式,如下所示:

Expression<Func<Product, StockDto>> expression = p => new StockDto
{
    Stock = StockLevel.Invoke(p) 
};

expression = expression.Expand();

var results = context
    .Products
    .Select(expression);

I hope I understood your question, take a look at this discussion. 我希望我理解你的问题,看看这个讨论。 You don't need extra argument, but the idea how to arrange things together might apply to your case. 您不需要额外的论证,但如何将事情安排在一起的想法可能适用于您的案例。

How to reuse LINQ Select Expression with arguments 如何重用LINQ选择带参数的表达式

private static Expression<Func<Singles, SearchSingles>> CreateSearchSelector()
{
    return s =>
        new SearchSingles
        {
            Foo = foo,
        };
}

// Then use it like this
DataContext.Single.Select(CreateSearchSelector()).ToList();

Look at Microsoft.Linq.Translations . 看看Microsoft.Linq.Translations It allows you to define properties with expression trees, and then use them in queries. 它允许您使用表达式树定义属性,然后在查询中使用它们。 For select reuse, indeed LinqKit is your friend, or check out this answer, if you really want to understand how it works :) 对于选择重用,确实LinqKit是你的朋友,或者看看这个答案,如果你真的想了解它是如何工作的:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM