Подтвердить что ты не робот

LINQ-to-SQL: хранимая процедура, которая возвращает одно скалярное значение?

Я использую LINQ-to-SQL для приложения, которое запрашивает устаревшую базу данных. Мне нужно вызвать хранимую процедуру, которая выбирает одно целое значение. Изменение хранимой процедуры не является вариантом.

Конструктор создает метод с этой сигнатурой:

private ISingleResult<sp_xal_seqnoResult> NextRowNumber([Parameter(DbType="Int")] System.Nullable<int> increment, [Parameter(DbType="Char(3)")] string dataset)

Я хотел бы, чтобы возвращаемый тип был int. Как это сделать, используя LINQ-to-SQL?

4b9b3361

Ответ 1

Это было бы тривиально со скалярной функцией (UDF), а не с SP. Однако он должен работать достаточно легко - хотя, если SP сложный (т.е. FMT_ONLY не может проверить его на 100%), вам может понадобиться "помочь" ему...

Вот некоторый dbml, который я создал из упрощенного SP, который возвращает целое число; вы можете редактировать dbml через "open with... xml editor" ):

<Function Name="dbo.foo" Method="foo">
    <Parameter Name="inc" Type="System.Int32" DbType="Int" />
    <Parameter Name="dataset" Type="System.String" DbType="VarChar(20)" />
    <Return Type="System.Int32" />
</Function>

(обратите внимание, что вам, очевидно, нужно настроить имена и типы данных).

И вот сгенерированный С#:

[Function(Name="dbo.foo")]
public int foo([Parameter(DbType="Int")] System.Nullable<int> inc, [Parameter(DbType="VarChar(20)")] string dataset)
{
    IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), inc, dataset);
    return ((int)(result.ReturnValue));
}

Если ваш текущий SP использует SELECT (вместо RETURN), тогда DBML должен будет отразить это. Вы можете исправить это, спрятав детали реализации и предоставив публичную обертку в частичном классе; например:

<Function Name="dbo.foo" Method="FooPrivate" AccessModifier="Private">
    <Parameter Name="inc" Type="System.Int32" DbType="Int" />
    <Parameter Name="dataset" Type="System.String" DbType="VarChar(20)" />
    <ElementType Name="fooResult" AccessModifier="Internal">
      <Column Name="value" Type="System.Int32" DbType="Int NOT NULL" CanBeNull="false" />
    </ElementType>
</Function>

В приведенном выше описании описывается SP, который возвращает одну таблицу с одним столбцом; но я сделал SP "private" для контекста данных, а результат - "внутренним" для сборки (скрывая ее):

[Function(Name="dbo.foo")]
private ISingleResult<fooResult> FooPrivate(
    [Parameter(DbType="Int")] System.Nullable<int> inc,
    [Parameter(DbType="VarChar(20)")] string dataset)
{
    IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), inc, dataset);
    return ((ISingleResult<fooResult>)(result.ReturnValue));
}

Теперь в моем собственном файле класса я могу добавить новый неполный класс (новый .cs файл) в правильное пространство имен, что более удобно предоставляет метод:

namespace MyNamespace {
    partial class MyDataContext
    {
        public int Foo(int? inc, string dataSet)
        {
            return FooPrivate(inc, dataSet).Single().value;
        }
    }
}

(имена пространств имен и контекстов должны быть такими же, как и фактический контекст данных). Это добавляет общедоступный метод, который скрывает детализацию от вызывающего.

Не редактировать файл designer.cs напрямую; ваши изменения будут потеряны. Редактируйте только dbml или частичные классы.

Ответ 2

RETURN @VALUE как последний оператор proc.

то он автоматически определит тип int, string, bool и т.д. и соответствующим образом создаст метод оболочки.

Ответ 3

Если вы используете файл Visual Studio.xsd в проекте классов Linq to SQL, убедитесь, что вы:

  • Щелкните правой кнопкой мыши вызов хранимой процедуры или функции в адаптере.
  • Выберите "Свойства"
  • Изменить режим выполнения на Scalar

Это приведет к тому, что ваша функция возврата адаптера вернется к "Объекту". Затем вам нужно передать его в int или string, или какой бы тип он ни был.