LINQ to SQL-No se puede modificar el tipo de devolución del procedimiento almacenado
linq-to-sql stored-procedures (11)
De acuerdo, encontré el problema ... más o menos. Cambié el nombre de la tabla "Asignaciones" y olvidé actualizar el procedimiento almacenado, por lo que el diseñador de DBML estaba confundido. PERO incluso después de que actualicé el procedimiento almacenado, lo eliminé del diseñador de DBML y lo reescribí, ¡no estaba funcionando!
Este es casi el mismo problema discutido aquí: http://forums.asp.net/t/1231821.aspx .
Solo funcionó cuando eliminé el procedimiento almacenado de la base de datos y lo recreé, y lo eliminé del diseñador de DBML, volví a compilarlo, reinicié Visual Studio y lo volví a agregar. Esta es la segunda vez que me encuentro con problemas de "actualización" con el diseñador Visual Studio DBML ...
Cuando arrastro un procedimiento almacenado en particular en el diseñador dbml de VS 2008, aparece con Tipo de devolución establecido en "ninguno", y es de solo lectura, por lo que no puedo modificarlo. El código del diseñador muestra que devuelve un int, y si lo cambio manualmente, simplemente se deshace en la siguiente compilación.
Pero con otro procedimiento almacenado (casi idéntico), puedo cambiar el tipo de devolución muy bien (de "Tipo generado automáticamente" a lo que deseo).
Me he encontrado con este problema en dos máquinas separadas. ¿Tienes idea de lo que está pasando?
Aquí está el procedimiento almacenado que funciona:
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
Y este no:
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
También he visto este problema varias veces y aunque no sé cuál es la causa, me he encontrado con una forma bastante fácil de superarlo. Implica editar manualmente el xml dentro del archivo .dbml, pero es una edición bastante simple.
Haga clic derecho en el archivo .dbml
del Contexto de .dbml
en el Explorador de soluciones (no en el archivo .layout ni en el archivo designer.cs) y ábralo con el Editor XML. Debería encontrar su procedimiento almacenado en la lista de un bloque <Function> ... </Function>
. También debería encontrar la clase personalizada que desea establecer como el Tipo de devolución enumerado en un bloque <Type> ... </Type>
.
El primer paso es dar a su clase personalizada un identificador. Para hacerlo, agregue una etiqueta "Id", así, asegurándose de que sea única dentro del archivo dbml:
<Type Name="MyCustomClass" Id="ID1">
El segundo paso es decirle a tu función que use el nuevo tipo de identificación como el Tipo de devolución. Lo haces al reemplazar la línea en tu bloque <Function>
que se parece a
<Return Type="System.Int32" />
con
<ElementType IdRef="ID1" />
Guarde el archivo, salga y reconstruya. Hecho. Vuelva a abrir el archivo .dbml en modo de diseño para verificar: su procedimiento ahora tendrá la clase personalizada configurada como el Tipo de devolución.
Esto también ocurre cuando se utilizan tipos definidos por el usuario sql como parámetros en procedimientos almacenados
Tuve el mismo problema, pero solo sucede si mi sp utiliza FTS, lo que hice fue "engañar" al diseñador de dbml, eliminé el lenguaje de fts y funcioné perfectamente, ahora puedo cambiar el tipo de devolución. Más tarde voy a la sp y agrego los fts de nuevo y funciona perfectamente !. Espero que esto ayude.
La forma de evitar este problema es:
- Agrega "set fmtonly off"; al comienzo de su procedimiento almacenado.
- Después de agregar esa declaración, obtenga DBML generando el código para su procedimiento almacenado.
Si el tipo de devolución de su procedimiento almacenado sigue siendo ''int'' en su código DBML, comente todo el código del procedimiento almacenado, cree una nueva instrucción SELECT cuyos tipos y nombres de campos devueltos coincidan con la instrucción SELECT del original y obtenga DBML regenere el código nuevamente. ¡Tiene que funcionar!
Seguí el enlace proporcionado por Tony para una mejor solución (la misma respuesta que la de Arash)
- lea el blog, especialmente la última parte, ya que hay algo a considerar al agregar SET FMTONLY OFF en su procedimiento almacenado.
Cuando agregas
SET FMTONLY OFF
al comienzo del procedimiento almacenado y cargarlo en DBML,
LINQ2SQL ejecutará el procedimiento almacenado real.
Para obtener el tipo de objeto de tabla de retorno correcto,
dicho procedimiento almacenado debe devolver algo cuando se lo llama parámetro (s) sin parámetros.
Eso significa:
1. Tener un valor predeterminado para todos los parámetros de entrada
2. Asegúrese de que SP devuelva al menos una fila de datos: aquí es donde tropecé
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;
Logré trabajar de una manera más fácil, que no era obvia en ese momento, pero suena directo cuando se escribe:
- Elimine el procedimiento almacenado de la superficie de diseño del archivo .dbml
- Haga clic en Guardar todos los archivos
- Haga clic en Actualizar en Server Explorer en la lista de Procedimientos almacenados
- Agregue (arrastre) el procedimiento almacenado nuevamente a la superficie de diseño del archivo .dbml
- Haga clic en Guardar todo
- Haz clic en Build
- Compruebe el archivo de código designer.cs y tendrá el código C actualizado para la nueva versión del procedimiento almacenado
revisa http://www.high-flying.co.uk/C-Sharp/linq-to-sql-can-t-update-dbml-file.html
Tuve un problema de mapeo similar, pero encontré al culpable en mi caso.
Si su procedimiento o cualquier subprocedimiento que se llama tiene objetos temporales como
CREATE TABLE #result (
ID INT,
Message VARCHAR(50)
)
entonces estás en problemas, incluso si no seleccionas nada de estos temporales.
El asignador tiene un problema general con estos objetos temporales, porque el tipo se puede cambiar fuera del procedimiento en el contexto de la sesión. Los objetos temporales no son seguros para el mapeador y él los rechaza.
Sustitúyalos por variables de tabla y ya está de vuelta en el negocio
DECLARE @result AS TABLE (
ID INT,
Message VARCHAR(50)
)
Gracias @Rubenz, también estaba usando FTS (Búsqueda de texto completo) en un procedimiento almacenado y sus pasos funcionó.
Comenté la sección FTS del procedimiento almacenado, agregué el procedimiento almacenado a .dbml y luego comencé a descomentar la sección FTS en original.
De acuerdo, no quería cambiar nada en mi código Designer.cs, sabía que había un problema diferente y no estaba relacionado con mi procedimiento almacenado (de todos modos, no estaba usando la tabla temporal).
Simplemente eliminar la sp de la base de datos y actualizar el modelo no ayudaba en absoluto. El nuevo modelo creado todavía tenía los mismos problemas ...
Lo que encontré es que, por alguna razón, se crearon copias de mi sp en DatabaseModel -> Function Imports.
Lo que hice, eliminé los objetos duplicados en Importaciones de funciones y actualicé el modelo. ¡Funcionó!
Saludos, Chris