简体   繁体   English

EF代码优先-在特定的十进制属性上具有乘法的IQueryable

[英]EF code-first - IQueryable having multiplication on a specific decimal property

I have been struggling with the following problem on Entity Framework code-first. 我一直在尝试以下有关实体框架代码优先的问题。

I have an entity class with a decimal, and I have a multiplier decimal parameter. 我有一个带小数的实体类,并且有一个乘数小数参数。

I want to build a query (but not to call it), which returns the entities, but the Bar property need to be multiplied with my parameter. 我想构建一个查询(但不调用它),该查询返回实体,但是Bar属性需要与我的参数相乘。

From coding side: 从编码方面:

public class Foo
{
    public Guid Id { get; set; }
    public Decimal Bar { get; set; }
}

// this simple stuff returns the entities after some filterings.
Context.Set<Foo>().Where(x => querying on many props).ToList();

This method is similiar what I want to achieve: 此方法与我想要实现的类似:

public IQueryable<Foo> GetFooQuery( .. Many properties used to the query .. , Decimal Multiplier)
{
    var IQueryablePart = Context.Set<Foo>().Where(querying with the parameters);

    /* ... and what to do here? ... */
    /* IQueryablePart = IQueryablePart.Select(x => new {
           Bar = Bar * Multiplier <-- this is okay
       }); */
    // but how to retrieve the other columns without listing them one by one, and how to return the data as IQueryable<Foo> ?

    return IQueryablePart;
}

I would like to use this method in the following way: 我想通过以下方式使用此方法:

IQueryable<Foo> FullQuery = null;   

for(some loop, may be 10 or 1000 iterations, it depends) {
    var Part = GetFooQuery(/* .. query params ..*/, 2);

    if(MyFullQuery == null) 
        FullQuery = Part;
    else 
        FullQuery.Union(Part);
}

// and in the end, do the db call once: 
var Result = FullQuery.ToList();

In SQL, I would handle it like this: 在SQL中,我将这样处理:

SELECT 
    Id,
    Bar * @MyValue as Bar, 
    # and all other columns
FROM 
    Foo 
WHERE 
    (param queries 1) OR 
    (param queries 2) OR
    ---
    (param queries N)

My question is: what is the way to do this via IQueryable and EF? 我的问题是:通过IQueryable和EF进行此操作的方式是什么? The most important, I need to call the db only one time. 最重要的是,我只需要一次调用数据库。

I reckon it may be some query building stuff, but I'm not familiar with it yet, any help will be very appreciated. 我认为这可能是一些查询构建的东西,但是我还不熟悉,任何帮助将不胜感激。

EF6 does not support projection ( select ) to a class mapped as entity. EF6不支持投影( select )到映射为实体的类。 Hence the only option you have is to project to some anonymous or special class. 因此,您唯一的选择是将项目投影到某些匿名或特殊类。 For your scenario, the easiest I see is a class like this: 对于您的情况,我最容易看到的是这样的类:

public class FooBar
{
    public Foo Foo { get; set; }
    public decimal Bar { get; set; }
}

Then the single query method could be like this: 那么单个查询方法可能是这样的:

public IQueryable<FooBar> GetFooQuery( .. Many properties used to the query .. , decimal multiplier)
{
    return Context.Set<Foo>()
        .Where(querying with the parameters)
        .Select(foo => new FooBar
        {
            Foo = foo,
            Bar = foo.Bar * multiplier
        });
}

Now you can build your full query: 现在,您可以构建完整的查询:

IQueryable<FooBar> fullQuery = null;

for (some loop, may be 10 or 1000 iterations, it depends)
{
    var subQuery = GetFooQuery(/* .. query params ..*/, 2);

    fullQuery = fullQuery == null ? subquery : fullQuery.Union(subQuery);
}

Note that if you use different multiplier (otherwise the whole procedure does not make sense), you'd better use LINQ Concat method (which translates to SQL UNION ALL ) rather then Union (which translates to SQL UNION ). 请注意,如果您使用其他乘数(否则整个过程没有意义),则最好使用LINQ Concat方法(将其转换为SQL UNION ALL ),而不是使用Union (将其转换为SQL UNION )。

Finally, you can materialize the result as Foo sequennce by executing the single final SQL query, switching to LINQ to Objects and converting the FooBar to Foo like this: 最后,你可以兑现的结果作为Foo通过执行单一的最终SQL查询,切换到LINQ到对象和转换sequennce FooBarFoo是这样的:

var result = fullQuery.
    .AsEnumerable() // db query ends here
    .Select(fooBar =>
    {
        fooBar.Foo.Bar = fooBar.Bar;
        return fooBar.Foo;
    })
    .ToList();

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

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