Entity Framework и импорт функций хранимых процедур с обнуляемыми параметрами - PullRequest
2 голосов
/ 16 апреля 2011

Я заметил, что когда Entity Framework генерирует метод для хранимой процедуры (импорт функции), он проверяет, является ли параметр нулевым, и принимает решение, подобное этому:

if (contactID.HasValue)
{
  contactIDParameter = new ObjectParameter("contactID", contactID);
}  
else
{
  contactIDParameter = new ObjectParameter("contactID", typeof(global::System.Int32));
}

Я не понимаю, что он пытается сделать, передав Тип параметра в качестве параметра, когда параметр равен нулю? Как именно выполняется хранимая процедура / функция в этом случае?

Я сам провел тестирование с помощью SQL Profiler и заметил, что когда я намеренно передаю null в качестве параметра (вызывая что-то вроде context.MyProcedure (null)), null просто передается в качестве параметра хранимой процедуре сервера SQL.

Буду признателен за некоторые разъяснения относительно этого поведения.

Ответы [ 2 ]

2 голосов
/ 17 апреля 2011

Меня заинтересовал этот вопрос, поэтому я провел некоторое исследование.

ObjectParameter имеет две перегрузки - одну для передачи значения и одну для передачи типа.Второй используется, если вы передаете null в качестве значения параметра, потому что это необходимо для EF.Причина в том, что импорт функции должен вызываться с ObjectParameters, а не с простыми параметрами, передаваемыми в метод обтекания.

Внутренние вызовы EF:

private EntityCommand CreateEntityCommandForFunctionImport(string functionName, out EdmFunction functionImport, params ObjectParameter[] parameters)
{
    ...
    for (int i = 0; i < parameters.Length; i++)
    {
        if (parameters[i] == null)
        {
            throw EntityUtil.InvalidOperation(Strings.ObjectContext_ExecuteFunctionCalledWithNullParameter(i));
        }
    }
    ...
    this.PopulateFunctionEntityCommandParameters(parameters, functionImport, command);
    return command;
}

Как видно даже нулевое значениедолжен быть представлен как ObjectParameter, потому что вы не можете просто передать null - он выдаст исключение.PopulateFunctionEntityCommandParameters использует информацию о типе для создания правильного DbParameter для вызова хранимой процедуры.Значение этого параметра DBNull.Value.

Так что вам не нужно иметь с ним дело.Это просто инфраструктура.

1 голос
/ 18 февраля 2013

Когда вы смотрите код класса ObjectParameter конструкторы

public ObjectParameter (string name, object value)
public ObjectParameter (string name, Type type)

Вы видите, что ObjectParameter имеет 3 важных приватных поля:

_name (имя параметра, не нулевое и неизменное), _type (тип параметра CLR, ненулевое и неизменное), _value (значение параметра, может быть изменено и обнулено)

Когда используется первый конструкторвсе эти поля инициализированы.Со вторым конструктором поле _value остается равным null.

В ExecuteFunction EF используется закрытый метод CreateEntityCommandForFunctionImport, который вызывает другой, еще более глубокий закрытый метод PopulateFunctionImportEntityCommandParametersкоторый присоединяет параметры сущности.

Внутри PopulateFunctionImportEntityCommandParameters, экземпляр EntityParameter, представляющий параметр в EntityCommand, будет сопоставлен со свойствами имени и значения ObjectParameter.

Эта инструкция объясняет все это:

entityParameter.Value = objectParameter.Value ?? DBNull.Value;

Мы передаем DBNull в EF, если в качестве параметра не было указано значение.

...