2009-05-29 14 views
18

Cuando arrastro un procedimiento almacenado particular en el diseñador dbml VS 2008, aparece con Tipo de devolución establecido en "ninguno", y solo se lee para que pueda no lo cambies El código del diseñador muestra que devuelve un int, y si lo cambio manualmente, simplemente se deshace en la siguiente compilación.LINQ to SQL - No se puede modificar el tipo devuelto del procedimiento almacenado

Pero con otro (casi idéntico) procedimiento almacenado, que puede cambiar el tipo de retorno muy bien (de "tipo generado Auto" para lo que quiero.)

me he encontrado con este problema en dos máquinas separadas . ¿Tienes idea de lo que está pasando?

Este es 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 esto uno no lo hace:

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 
+0

yo nos encontramos con el problema cuando se trata de añadir un SP que consulta una tabla que no existía en esa base de datos. –

Respuesta

5

Está bien, me encontré con 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 borré del diseñador de DBML y lo reescribí, ¡no estaba funcionando!

Esto es casi el mismo problema discutido aquí: http://forums.asp.net/t/1231821.aspx.

Funcionó solo cuando eliminé el procedimiento almacenado de la base de datos y lo recreé, lo eliminé del diseñador de DBML, recompilé, 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 ...

18

También he visto este problema varias veces y aunque no sé cuál es la causa, he encontrar una manera bastante fácil de superarlo. Implica editar manualmente el xml dentro del archivo .dbml, pero es una edición bastante simple.

Haga clic con el botón derecho en el archivo .dbml del Contexto de datos 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 listado en un bloque <Function> ... </Function>. También debe encontrar la clase personalizada que desea establecer como el Tipo de devolución enumerado en un <Type> ... </Type> bloque.

El primer paso es dar a su clase personalizada un identificador. Lo hace mediante la adición de una etiqueta de "Id", de esta manera, asegurándose de que es único dentro del archivo dbml:

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

El segundo paso es decirle a su función para utilizar el tipo de nueva Identifican como el tipo de retorno . Lo hace por reemplazando la línea en su bloque <Function> que se parece a

<Return Type="System.Int32" /> 

con

<ElementType IdRef="ID1" /> 

Guarde el archivo de salida, y reconstruir. 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.

+1

Descubrí que también necesitaba editar el archivo .designer.cs para actualizar el tipo de devolución para el método de procedimiento almacenado. De lo contrario, el método de procedimiento almacenado aún devolvería un int cuando se utiliza en el código. – Tarsier

1

que tenía el mismo problema, pero sólo ocurre si mi sp utiliza FTS, lo que hice fue "trampa" el diseñador dbml, elimino el lenguaje fts y funciono 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 esta ayuda.

12

que tenía un problema de asignación similar, pero me encontré con el culpable en mi caso.

Si el procedimiento o cualquier subprocedimiento que es llamada tiene objetos temporales como

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

entonces estás en problemas, incluso si no se selecciona 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.

reemplazarlas por las variables de tabla y que está de vuelta en los negocios

DECLARE @result AS TABLE (
    ID INT, 
    Message VARCHAR(50) 
) 
+1

Me preguntaba si esto estaba documentado en alguna parte, he estado buscando un día completo antes de encontrar esto – CheGueVerra

1

La manera de solucionar este problema es:

  1. Añadir "set FMTONLY fuera;" al comienzo de su procedimiento almacenado.
  2. 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 el código DBML, comentar el código completo del procedimiento almacenado, crear una nueva instrucción SELECT cuya volver tipos de campos y nombres coinciden instrucción SELECT del original y obtener DBML regenerar el código otra vez ¡Tiene que funcionar!

9

he seguido el link provided by Tony para una mejor solución (misma respuesta que Arash de)

  • ¿Lee el blog, sobre todo la última parte, porque no es una cosa a considerar cuando se añade SET FMTONLY OFF en su procedimiento almacenado.

Cuando se agrega

SET FMTONLY OFF 

en el inicio del procedimiento almacenado y lo carga a DBML,
LINQ2SQL sería ejecutar el procedimiento almacenado real.

Para obtener el tipo de objeto de la tabla de devolución correcta,
dicho procedimiento almacenado debe devolver algo cuando se lo llame sin parámetros.
Eso significa:
1.Tener un valor por defecto para todos los parámetros de entrada
2. Asegúrese de SP regresa al menos una fila de datos - aquí es donde me encontré

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

logré averiguar una manera más fácil, que no era obvio en el momento, pero suena sencillo cuando se escribe:

  1. Eliminar el procedimiento almacenado desde la superficie de diseño del archivo .dbml
  2. Haga clic en Guardar todos los archivos
  3. Haga clic en Actualizar en el Explorador de servidores en el lista de procedimientos almacenados
  4. Añadir (arrastre) el procedimiento almacenado de nuevo en la superficie de diseño del archivo .dbml
  5. Haga clic en Guardar todo
  6. haga clic en Generar
  7. comprobar el archivo de código designer.cs y usted tendrá la actualizado el código C# para la nueva versión del procedimiento almacenado

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

1

Gracias @Rubenz, yo también estaba usando FTS (búsqueda de texto completo) en un procedimiento almacenado y su Pasos trabajados.

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.

0

Bien, 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 (no utilicé la tabla temporal de todos modos).

Simplemente eliminando la sp de la base de datos y actualizando el modelo no ayudó 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

Cuestiones relacionadas