2017-08-15 30 views
1

我一直在以代码优先的方式在实体框架上遇到以下问题。EF代码优先 - IQueryable在特定的小数属性上有乘法

我有一个小数的实体类,我有一个乘数小数参数。

我想构建一个查询(但不能调用它),它返回实体,但Bar属性需要与我的参数相乘。

从编码侧:

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(); 

这种方法类同什么我想要实现:

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; 
} 

我想通过以下方式来使用此方法:

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(); 

在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) 

我的问题是:如何通过IQueryable和EF来做到这一点?最重要的是,我只需要一次调用db。

我认为它可能是某些查询的建筑的东西,但我不熟悉它,但任何帮助将是非常赞赏。

+1

如果两个'Bar'和'myvalue的:

最后,你可以通过执行单一的最终SQL查询,切换到LINQ到对象和转换FooBarFoo这样兑现的结果作为Foo sequennce '是相同的表(即实体)的一部分,那么合乎逻辑的解决办法是在你的代码,而不是一个自动属性检索。 – silkfire

+0

不幸的是,他们不是。乘数由代码计算。 –

+0

你从哪里得到@MyValue? – silkfire

回答

0

EF6不支持将投影(select)映射为映射为实体的类。因此,你唯一的选择是投射到一些匿名或特殊的班级。对于您的情况,我看最简单的就是这样的一类:

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

然后单查询方法可能是这样的:

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 
     }); 
} 

现在你可以建立完整的查询:

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); 
} 

请注意,如果您使用不同的乘数(否则整个过程没有意义),你最好使用LINQ Concat方法(这相当于SQL UNION ALL),而TH恩Union(这相当于SQL UNION)。

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

乘法器在不同迭代之间变化,所以我的目标是在数据从数据库中拉出之后,让db在代码中计算乘法而不是“me”。 –

+0

这个传输类的解决方案在db中进行了计算,但是,我仍然需要在调用完整查询后选择元素,但比使用该方法后进行后期计算更优​​雅,而且我仍然有“额外的工作“,无论如何都要对查询进行拼接。感谢您的解决方案。 –