2010-01-18 18 views
5

¿Cómo obtendré el número de identificación de clave principal de una Tabla sin haciendo un segundo viaje a la base de datos en LINQ To SQL?¿Cómo obtener la clave primaria de una tabla sin hacer un segundo viaje?

En este momento, envío los datos a una tabla, y realizo otro viaje para descubrir qué ID se asignó al nuevo campo (en un campo de ID de incremento automático). Quiero hacer esto en LINQ To SQL y no en Raw SQL (ya no uso Raw SQL).

Además, la segunda parte de mi pregunta es: siempre tengo cuidado de conocer el ID de un usuario que está en línea porque prefiero llamar su información en varias tablas usando su ID en lugar de usar un GUID o un nombre de usuario. que son todas cadenas largas. Lo hago porque creo que SQL Server haciendo una comparación numérica es mucho (?) Más eficiente que hacer un nombre de usuario (cadena) o incluso un guid (cadena muy larga) comparar. Mi pregunta es, ¿estoy más preocupado de lo que debería estar? ¿Vale la pena mantener siempre el ID de usuario (int32) en estado de sesión?


@RedFilter proporciona algunas pistas interesantes/prometedores para la primera pregunta, porque estoy en esta etapa no puede probarlos, si alguien sabe o puede confirmar estos cambios que se recomienda en la sección de comentarios de su respuesta?

Respuesta

0

En T-SQL, puede utilizar la cláusula OUTPUT, diciendo:

INSERT table (columns...) 
OUTPUT inserted.ID 
SELECT columns... 

lo tanto, si se puede configurar para usar LINQ que construyen para hacer inserciones, entonces es probable que pueda recuperarlo fácilmente. Pero si LINQ puede obtener un valor de un inserto, dejaré que alguien más responda eso.

+0

no sé cómo escribir procedimientos sql en sql lang. pero si pudiera estar bastante seguro de que linq puede mapear los procedimientos almacenados sql en su diseñador de archivos .dbml, entonces debería poder obtener valores de retorno, probablemente solo si hace todo el INSERT usando t-sql ... de lo contrario no estoy seguro también. –

+0

No creo InsertOnSubmit o Enviar como un valor de retorno que sea relevante para nuestras necesidades. –

2

Linq to SQL establece automáticamente el valor de identidad de su clase con la ID generada cuando inserta un nuevo registro. Solo acceda a la propiedad. No sé si utiliza una consulta separada para esto o no, nunca lo ha usado, pero no es raro que los ORM requieran otra consulta para recuperar el último ID insertado.

dos formas de hacer esto independiente de LINQ to SQL (que puede trabajar con él):

1) Si está utilizando SQL Server 2005 o superior, puede utilizar la cláusula OUTPUT:

Devuelve información de expresiones basadas en cada fila afectada por una instrucción INSERT, UPDATE o DELETE. Estos resultados pueden ser devueltos a la aplicación de procesamiento para su uso en cosas tales como mensajes de confirmación , archivado y otros requisitos de la aplicación . Alternativamente, los resultados se pueden insertar en una variable de tabla o tabla.

2) Alternativamente, se puede construir una instrucción INSERT de este lote:

insert into MyTable 
(field1) 
values 
('xxx'); 
select scope_identity(); 

que funciona al menos tan atrás como SQL Server 2000.

+0

hola orbMan, si linq to sql auto actualizó la columna de identificación de una clase después de un SubmitChanges, sería fantástico, ¿alguien podría confirmar esto? –

+0

@ Erx_VB.NExT.Coder: Actualizará la columna de identificación en las inserciones, si se lo indica. Por defecto, si su columna de identificación es del tipo int, se establecerá automáticamente en "generated on insert", si es de tipo GUID, entonces debe cambiar la configuración predeterminada a "generate on insert". Lo haces desde el diseñador SQL de Linq 2. –

+0

@EgilHansen ah, fantástico, porque cuando probé esto, no funcionó de la caja, implementaré estos cambios e intentaré de nuevo y le contaré cómo va (tan pronto como regrese a este proyecto particular u otro que usa LINQ to SQL). –

4

A menos que usted está haciendo algo fuera de lo normal, no debería necesitar hacer nada adicional para recuperar la clave primaria que se genera.

Cuando llama al SubmitChanges en su contexto de datos de Linq-to-SQL, actualiza automáticamente los valores de las claves principales para sus objetos.

En cuanto a su segunda pregunta, puede haber una pequeña mejora en el rendimiento haciendo un escaneo en un campo numérico en lugar de algo como varchar() pero verá un mejor rendimiento de cualquier manera asegurándose de tener las columnas correctas en su base de datos indexada Y, con SQL Server, si crea una clave principal utilizando una columna de identidad, tendrá de manera predeterminada un índice agrupado sobre ella.

+0

hola, gracias, su derecho se incrementó automáticamente durante SubmitChange, eso no es un problema - necesito mantener este número/id para usarlo para llamar a otros registros realmente, esa es la única razón por la que quiero que esté en estado de sesión. –

12

Si tiene una referencia al objeto, puede simplemente usar esa referencia y llamar a la clave principal después de llamar al db.SubmitChanges(). El objeto LINQ actualizará automáticamente su campo de clave principal (Identificador) para reflejar el nuevo asignado a él a través de SQL Server.

Ejemplo (vb.net):

Dim db As New NorthwindDataContext 
    Dim prod As New Product 
    prod.ProductName = "cheese!" 
    db.Products.InsertOnSubmit(prod) 
    db.SubmitChanges() 
    MessageBox.Show(prod.ProductID) 

Probablemente podría incluir el código anterior en una función y devolver el ProductID (o clave primaria equivalente) y usarla en otro lugar.

EDITAR: Si no está haciendo actualizaciones atómicas, puede agregar cada nuevo producto a una Colección separada e iterar a través de él después de llamar a SubmitChanges. Ojalá LINQ proporcionara un 'adelanto de la base de datos' como lo haría un conjunto de datos.

+0

@calico: gracias amigo que fue explicado perfectamente, también refrescante para ver un código vb aquí de vez en cuando, dado tu voto positivo y aceptar la respuesta, así que ahora puedes comenzar a votar negativamente :) –

+0

solo para que lo sepas, intenté llama al PorductID de un objeto al que se hace referencia después de enviarlo y no funcionó en absoluto. aunque no he probado tu código anterior "tal como está", pero en principio era el mismo, ¿hay alguna idea de por qué puede ser quisquilloso? –

+0

¿Estás seguro de que la presentación fue exitosa? ¿Estás seguro de que sigues haciendo referencia al mismo objeto? No conozco tu código, así que no puedo estar seguro. –

0

Llamar a un procedimiento almacenado de LINQ que devuelve la ID como un parámetro de salida es probablemente el enfoque más fácil.

Cuestiones relacionadas