linq 'переменная диапазона' проблема - PullRequest
1 голос
/ 18 июня 2009

У меня странная проблема при удалении записей с помощью linq, я подозреваю, что это как-то связано с переменной диапазона (с именем source). После удаления записи все цели для клиента извлекаются с использованием следующего оператора:

var q = from source in unitOfWork.GetRepository<db_Target>().Find()
  where source.db_TargetBase.db_Person.fk_Customer == customerID
  select source.FromLinq();

где FromLinq находится в методе расширения для db_target:

public static Target FromLinq(this db_Target source)
{
    return new Target
    {
        id = source.id,
        LastModified = source.db_TargetBase.LastModified,
        ...
     }
}

При удалении записи удаляются db_Target и db_TargetBase. Например, когда два пользователя удаляют записи, linq пытается получить запись для пользователя user2, которая была удалена пользователем user1, что вызывает сбой в строке LastModified = source.db_TargetBase.LastModified, поскольку db_TargetBase равен null.

При использовании следующего кода проблема не возникает, и извлекаются только не удаленные записи:

var q = from source in unitOfWork.GetRepository<db_Target>().Find()
    where source.db_TargetBase.db_Person.fk_Customer == customerID
    select new Target
    {
        id = source.id,
        LastModified = source.db_TargetBase.LastModified,
        ...
    };

Это порождает два вопроса:

  1. Что здесь происходит? Я делаю копию переменной диапазона source, потому что я использую ее в методе расширения?
  2. Как мне "обернуть" код return new Target? Я использую это в нескольких местах и ​​не хочу копировать каждый раз. Трудно поддерживать мой код.

ТИА

JJ

1 Ответ

1 голос
/ 19 июня 2009

В первом наборе кода - поскольку инициализатор использует непереводимый метод (расширение или иное), он не может быть переведен - поэтому он запускается локально.

Во втором наборе кода - инициализатор представлен выражением elementinit, которое переводится (проверьте / сравните предложение select сгенерированного sql для доказательства).


Если вы хотите обернуть это, вам нужно иметь Expression<Func<db_Target, Target>>, который любой может получить и использовать в своем запросе. К счастью, это легко сделать:

public Expression<Func<db_Target, Target>> GetFromLinqExpressionForTarget()
{
  return
    source => new Target
    {
      id = source.id,
      LastModified = source.db_TargetBase.LastModified,
      ...
    }
}

Что можно использовать так:

var FromLinq = GetFromLinqExpressionForTarget();
var q =
(
   from source in ...
   ...
   ...
   select source
).Select(FromLinq);

Теперь ... Я действительно догадываюсь, и только на 60% уверен, что мой ответ правильный. Так что, если кто-то захочет это подтвердить, это сделает мой день. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...