динамически менять LINQ на запрос сущности - PullRequest
3 голосов
/ 19 марта 2012
int year = 2009; // get summ of TONS2009 column

var query = from ODInfo in DataContext.CIMS_TRUCKS
            where pLocationIDs.Contains(ODInfo.OID) 
            group ODInfo by ODInfo.OID into g
            select new
            {
               OID = g.Key,
               TotalTons = g.Sum( ODInfo => ODInfo.TONS2009)
            };

В выражении 'ODInfo => ODInfo.TONS2009' как мне изменить TONS2009 на TONS2010 или TONS2011 на основе параметра метода 'int year'?

Ответы [ 5 ]

3 голосов
/ 19 марта 2012

K06a ответ близок, но не будет работать на стороне сервера. Попробуйте это:

IEnumerable<OutputType> myQuery(IEnumerable<InputType> data, Expression<Func<InputType,decimal>> expr)
{
    return from ODInfo in DataContext.CIMS_TRUCKS
           where pLocationIDs.Contains(ODInfo.OID) 
           group ODInfo by ODInfo.OID into g
           select new OutputType
          {
              OID = g.Key,
              TotalTons = g.AsQueryable().Sum(expr)
           };
}

var query = myQuery(DataContext.CIMS_TRUCKS, ODInfo => ODInfo.TONS2009);

Я не пробовал этого, но сделал что-то подобное здесь .

UPDATE

Если вам действительно нужно преобразовать входные строки (например, «2009») в выражения, это все еще возможно:

string year = "2009";

Type ODInfoType = typeof(ODINFOTYPE); // substitute with the type of ODInfo
ParameterExpression pe = ParameterExpression.Parameter(ODInfoType, "ODInfo");
MemberInfo mi = ODInfoType.GetProperty("TONS" + year);
MemberExpression me = Expression.MakeMemberAccess(pe, mi);
var expr = Expression.Lambda<Func<ODINFOTYPE, decimal>>(me, pe);

Помните, что это патч для чрезвычайно злой структуры вашей базы данных.

1 голос
/ 20 марта 2012

Лучшее решение - разбить это на несколько запросов, которые вы можете составить для окончательного запроса:

int year = 2009; // get summ of TONS2009 column

var odInfos =
   year == 2009 ? DataContext.CIMS_TRUCKS.Select(x => new { x.OID, TONS = x.TONS2009 })
   year == 2010 ? DataContext.CIMS_TRUCKS.Select(x => new { x.OID, TONS = x.TONS2010 })
   year == 2011 ? DataContext.CIMS_TRUCKS.Select(x => new { x.OID, TONS = x.TONS2011 })
   : null;

var query = from ODInfo in odInfos
            where pLocationIDs.Contains(ODInfo.OID) 
            group ODInfo by ODInfo.OID into g
            select new
            {
               OID = g.Key,
               TotalTons = g.Sum(ODInfo => ODInfo.TONS)
            };

Это будет специализироваться на трех возможных запросах во время выполнения, тем самым обеспечивая максимальную производительность. Это лучше, чем чехол-переключатель.

1 голос
/ 19 марта 2012

Вы можете попробовать что-то вроде этого:

TotalTons = g.Sum( ODInfo => (year == 2009) ? ODInfo.TONS2009 : ((year == 2010) 
                                            ? ODInfo.TONS2010 : ODInfo.TONS2011))

Или сделать его более читабельным и использовать { }, чтобы разбить это лямбда-выражение на более чем одну строку и использовать, например.оператор switch.

0 голосов
/ 20 марта 2012

Использование DynamicLinq , который также работает с EF:

int year = 2009; // get summ of TONS2009 column

var query = from ODInfo in DataContext.CIMS_TRUCKS
            where pLocationIDs.Contains(ODInfo.OID) 
            group ODInfo by ODInfo.OID into g
            select g;

var projectedGroups = query.Select("new (Key as OID, Sum(TONS" + year + ") as TotalTons)");
0 голосов
/ 19 марта 2012

Попробуйте так:

IEnumerable<OutputType> myQuery(IEnumerable<InputType> data, Func<InputType,decimal> func)
{
    return from ODInfo in data
           where pLocationIDs.Contains(ODInfo.OID) 
           group ODInfo by ODInfo.OID into g
           select new OutputType
           {
              OID = g.Key,
              TotalTons = g.Sum(func)
           };
}

var query = myQuery(DataContext.CIMS_TRUCKS, ODInfo => ODInfo.TONS2009);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...