LINQ to SQL - невозможно изменить тип возвращаемого значения хранимой процедуры - PullRequest
20 голосов
/ 29 мая 2009

Когда я перетаскиваю определенную хранимую процедуру в конструктор dbml VS 2008, она отображается с типом возвращаемого значения «none» и доступна только для чтения, поэтому я не могу ее изменить. Код конструктора показывает, что он возвращает int, и если я изменяю его вручную, он просто отменяется при следующей сборке.

Но с другой (почти идентичной) хранимой процедурой я могу очень просто изменить тип возвращаемого значения (с "Auto Generated Type" на то, что я хочу.)

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

Вот хранимая процедура, которая работает:

USE [studio]
GO
/****** Object:  StoredProcedure [dbo].[GetCourseAnnouncements]    Script Date: 05/29/2009 09:44:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[GetCourseAnnouncements]
    @course int
AS
SELECT * FROM Announcements WHERE Announcements.course = @course
RETURN

А этот нет:

USE [studio]
GO
/****** Object:  StoredProcedure [dbo].[GetCourseAssignments]    Script Date: 05/29/2009 09:45:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[GetCourseAssignments]
    @course int
AS
SELECT * FROM Assignments WHERE Assignments.course = @course ORDER BY date_due ASC
RETURN

Ответы [ 12 ]

19 голосов
/ 28 августа 2009

Я также видел эту проблему несколько раз, и хотя я не знаю, что ее вызывает, я наткнулся на довольно простой способ ее преодоления. Он включает ручное редактирование xml в файле .dbml, но это довольно простое редактирование.

Щелкните правой кнопкой мыши файл .dbml вашего контекста данных в обозревателе решений (не файл .layout или файл designer.cs) и откройте его с помощью редактора XML. Вы должны найти свою хранимую процедуру в списке <Function> ... </Function>. Вы также должны найти пользовательский класс, который вы хотите установить в качестве Типа возврата, указанного в блоке <Type> ... </Type>.

Шаг первый - присвоить вашему пользовательскому классу идентификатор. Это можно сделать, добавив тег «Id», например, чтобы убедиться, что он уникален в файле dbml:

<Type Name="MyCustomClass" Id="ID1">

Шаг второй - указать вашей функции использовать новый тип идентификатора в качестве возвращаемого типа. Вы делаете это путем замены строки в вашем блоке <Function>, которая выглядит как

<Return Type="System.Int32" />

с

<ElementType IdRef="ID1" />

Сохраните файл, выйдите и восстановите. Готово. Снова откройте файл .dbml в режиме конструктора, чтобы убедиться, что в вашей процедуре для настраиваемого класса задан тип возвращаемого значения.

13 голосов
/ 25 ноября 2010

У меня была похожая проблема с отображением, но я нашел виновника в моем случае.

Если ваша процедура или любая вызываемая подпроцедура имеют временные объекты, такие как

CREATE TABLE #result (
   ID INT,
   Message VARCHAR(50)
)

тогда у вас проблемы, даже если вы ничего не выберете из этих временных.

У преобразователя есть общая проблема с этими временными объектами, потому что тип может быть изменен вне процедуры в контексте сеанса. Временные объекты не являются безопасными для картографа, и он отказывается от их использования.

Замените их табличными переменными, и вы снова в деле

DECLARE @result AS TABLE (
   ID INT,
   Message VARCHAR(50)
)
9 голосов
/ 30 марта 2011

Я перешел по ссылке , предоставленной Тони для лучшего решения (тот же ответ, что и у Араша)

  • Прочтите блог, особенно последнюю часть, потому что при добавлении SET FMTONLY OFF в вашей хранимой процедуре нужно учесть.

Когда вы добавляете

 SET FMTONLY OFF

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

Чтобы получить правильный тип возвращаемого объекта таблицы,
указанная хранимая процедура должна что-то возвращать при вызове без параметров.
Это значит:
1. Имеют значение по умолчанию для всех входных параметров
2. Убедитесь, что SP возвращает хотя бы строку данных - вот где я споткнулся

create table #test ( text varchar(50) );
insert into #test (text) values ('X'); -- w/o this line, return type would be Int32
select * from #test; -- SP returns something, proper object type would be generated
return;
5 голосов
/ 22 ноября 2011

Мне удалось выработать более простой способ, который в то время не был очевиден, но звучит прямо, когда записано:

  1. Удалить хранимую процедуру из области конструктора файла .dbml
  2. Нажмите Сохранить все файлы
  3. Нажмите Обновить в обозревателе серверов в списке хранимых процедур
  4. Добавить (перетащить) хранимую процедуру обратно на поверхность конструктора .dbml файла
  5. Нажмите Сохранить все
  6. Нажмите Build
  7. Проверьте файл кода designer.cs, и вы получите обновленный код C # для новой версии хранимой процедуры

check http://www.high -flying.co.uk / C-Sharp / linq-to-sql-can-t-update-dbml-file.html

5 голосов
/ 30 мая 2009

Хорошо, я нашел проблему ... вроде. Я изменил имя таблицы «Назначения» и забыл обновить хранимую процедуру, поэтому дизайнер DBML был сбит с толку. НО даже после того, как я обновил хранимую процедуру, удалил ее из конструктора DBML и прочитал ее, она не работала!

Это почти та же проблема, что обсуждалась здесь: http://forums.asp.net/t/1231821.aspx.

Это сработало только тогда, когда я удалил хранимую процедуру из базы данных и воссоздал ее, удалил из конструктора DBML, перекомпилировал, перезапустил Visual Studio и снова добавил. Это второй раз, когда я сталкиваюсь с проблемами "обновления" с конструктором Visual Studio DBML ...

1 голос
/ 02 ноября 2012

Спасибо @Rubenz, я также использовал FTS (полнотекстовый поиск) в хранимой процедуре, и ваши шаги сработали.

Я прокомментировал раздел FTS из хранимой процедуры, добавил хранимую процедуру в .dbml, а затем раскомментировал раздел FTS обратно в исходный.

1 голос
/ 16 февраля 2011

Способ обойти эту проблему:

  1. Добавить "set fmtonly off;" к началу вашей хранимой процедуры.
  2. После добавления этого оператора получить DBML сгенерировать код для вашей хранимой процедуры.

Если тип возвращаемого значения вашей хранимой процедуры по-прежнему равен 'int' в вашем коде DBML, закомментируйте весь код хранимой процедуры, создайте новый оператор SELECT, чьи возвращаемые типы полей и имена совпадают с исходным оператором SELECT, и получите DBML для повторного создания кода снова , Это должно работать!

1 голос
/ 29 декабря 2009

У меня была такая же проблема, но она случается только в том случае, если мой sp использует FTS, то, что я сделал, «обманул» конструктор dbml, я удалил язык fts и работает отлично, теперь я могу изменить тип возвращаемого значения. Позже я иду к SP и добавить FTS снова и работает отлично !. Надеюсь, что это поможет.

0 голосов
/ 31 января 2019

Я понимаю, что это старый вопрос, но приведенные выше предложения указали мне верное направление, но в моем случае это не сработало. В итоге я отредактировал файл dbml с помощью XML-редактора в Visual Studio, как предложено выше.

Попав в файл, найдите раздел «Функции» для хранимой процедуры. Скорее всего, вы не увидите раздел ElementType, который определяет тип возвращаемого значения. Я начал редактировать поля из другой функции (хранимой процедуры) и обнаружил, что это слишком утомительно и может создавать проблемы.

Я решил удалить все определения столбцов из ElementType - но оставьте раздел ElementType и сохраните файл. Затем я удалил хранимую процедуру из конструктора и снова добавил ее. Затем он заполнил правильные столбцы в ElementType. Работал красиво.

0 голосов
/ 13 октября 2014

ОК, я не хотел ничего менять в своем коде Designer.cs, я знал, что была другая проблема, и она не была связана с моей хранимой процедурой (я все равно не использовал временную таблицу).

Простое удаление sp из базы данных и обновление модели не помогли вообще. У новой созданной модели все еще были те же проблемы ...

Я обнаружил, что по какой-то причине копии моего sp были созданы в DatabaseModel -> Import Imports.

Что я сделал, я удалил дублирующиеся объекты в Импорт функций и обновил модель. Сработало!

С уважением, Chris

...