2009-03-12 9 views
6

Estoy usando Linq para SQL. Tengo un DataContext contra el cual soy .SubmitChanges() 'ing. Hay un error de insertar el campo de identidad: Linq to SQL: ¿Por qué obtengo los errores IDENTITY_INSERT?

Cannot insert explicit value for identity column in table 'Rigs' when IDENTITY_INSERT is set to OFF.

El único campo de identidad es "ID", que tiene un valor de 0. Se define en el DBML como:

[Column(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] 

Hay unos pocos extranjera claves, y he verificado que tienen valores que coinciden con el contenido de tablas extranjeras.

¿Por qué recibiría este error?

Editar: Aquí está la consulta:

exec sp_executesql N'INSERT INTO [dbo].[Rigs]([id], [Name], [RAM], [Usage], [MoreInfo], [datetime], [UID]) 
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6) 
SELECT [t0].[id], [t0].[OSID], [t0].[Monitors] 
FROM [dbo].[Rigs] AS [t0] 
WHERE [t0].[id] = @p7',N'@p0 int,@p1 varchar(1),@p2 int,@p3 varchar(1),@p4 varchar(1),@p5 datetime,@p6 int,@p7 
int',@p0=0,@p1='1',@p2=NULL,@p3='4',@p4='5',@p5=''2009-03-11 20:09:15:700'',@p6=1,@p7=0 

Está claro que está pasando un cero, a pesar de no haber sido asignado un valor.

Editar Agregar código:

Rig rig = new Rig(); 
int RigID; 
try 
{ // Confirmed these always contain a nonzero value or blank 
    RigID = int.Parse(lbSystems.SelectedValue ?? hfRigID.Value); 
    if (RigID > 0) rig = mo.utils.RigUtils.GetByID(RigID); 
} 
catch { } 

rig.Name = Server.HtmlEncode(txtName.Text); 
rig.OSID = int.Parse(ddlOS.SelectedValue); 
rig.Monitors = int.Parse(txtMonitors.Text); 
rig.Usage = Server.HtmlEncode(txtUsage.Text); 
rig.MoreInfo = Server.HtmlEncode(txtMoreInfo.Text); 
rig.RigsToVideoCards.Clear(); 
foreach (ListItem li in lbYourCards.Items) 
{ 
    RigsToVideoCard r2vc = new RigsToVideoCard(); 
    r2vc.VCID = int.Parse(li.Value); 
    rig.RigsToVideoCards.Add(r2vc); 
} 
rig.UID = c_UID > 0 ? c_UID : mo.utils.UserUtils.GetUserByToken(this.Master.LiveToken).ID; 

if (!mo.utils.RigUtils.Save(rig)) 
    throw new ApplicationException("There was an error saving your Rig. I have been notified."); 
hfRigID.Value = rig.id.ToString(); 

public static User GetUserByToken(string token) 
{ 
    DataClassesDataContext dc = new DataClassesDataContext(ConfigurationManager.ConnectionStrings["MultimonOnlineConnectionString"].ConnectionString); 
return (from u in dc.Users 
    where u.LiveToken == token 
    select u).FirstOrDefault(); 
} 

Además, noto que cuando actualizo una plataforma (InsertOnSubmit) existente, que no actualiza. Profiler ni siquiera muestra ninguna consulta en ejecución.

+0

¿Puede incluir el código donde crea el objeto y lo agrega al DataContext? – Portman

+0

Yo segundo Portman, por favor publique el código que está usando para la inserción, vea mi respuesta, es probable que el problema esté allí – eglasius

Respuesta

7

¿Su código establece el valor de ID explícitamente en 0? (en lugar de dejarlo intacto).

Actualización 1: Como ha publicado en la versión actualizada, linq2sql está claramente pasando el valor a la base de datos. Aquí está uno que no he tenido ningún problema con:

[Column(Storage="_CustomerID", AutoSync=AutoSync.Always, DbType="Int NOT NULL IDENTITY", IsDbGenerated=true)] 
public int CustomerID 

acabo de ver a otro, y tiene la misma definición exacta de la que está utilizando.

[Column(Storage="_TestID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] 
public int TestID 

Actualización 2: En cuanto a actualizaciones, no tienen que hacer InsertOnSubmit para eso. Simplemente actualice los valores y llame a .SubmitChanges (debería lanzar una excepción). En el inserto, es realmente extraño, ya que los atributos de la propiedad que publicó parecen ser correctos, por lo que el método Insertar que genera linq2sql también debería ser correcto. Intentaría volver a agregar la tabla al diseñador y verificar que todas las propiedades sean correctas.

Tenga en cuenta que el método de inserción generada debe ser similar (con un matchingRig_Insert):

private void InsertRig(Rig obj) 
{ 
    System.Nullable<int> p1 = obj.Id; 

this.Rig_Insert (/ * montón de valores * /, ref P1); obj.Id = p1.GetValueOrDefault(); }

+0

Excepto que la segunda definición tiene "IsPrimaryKey = true", agregado a ella. – Chris

+0

@Chris, dije la definición samed como la que él está usando;) – eglasius

+0

@Freddy, disculpe mi ignorancia, estoy cansado del trabajo, ¿cómo son lo mismo? – Chris

1

si está suministrando el valor de la columna IDENTITY, debe agregar

SET IDENTITY_INSERT ON 

antes de que sus sentencias SQL, y

SET IDENTITY_INSERT OFF 

después de apagarlo. Eso vale para CUALQUIER SQL crudo.Si utilizó LINQ para crear un objeto como:

var customer = new LinqContext.Customer; 
customer.FirstName = "Bob"; 
customer.LastName = "Smith"; 

LinqContent.Customer.Add(customer); 
LinqContext.SubmitChanges(); 

Creo que funcionará, perdóneme si tengo clases incorrectas. Usted obtiene la idea básica.

Editar: Vaya .. Lo sentimos, no leyó toda la cuestión, lo retiro, cansado y fatigado del trabajo ...

+0

él no lo está haciendo a propósito, eso causaría que inserte 0 ... luego fallará en las inserciones duplicadas – eglasius

1

parece como su identificación se le ha asignado en alguna parte (aunque sólo sea por defecto a 0) - ¿Te importaría publicar algo de tu código LINQ?

2

Asegúrese de que la propiedad Valor generado automáticamente en su archivo dbml para esa columna esté establecida en verdadero. De lo contrario, LINQ intentará establecer el valor por defecto según el tipo.

10

Mi teoría de lo sucedido es como sigue:

  1. Usted diseñado y creado la Base de Datos
  2. que ha creado el contexto DB usando LINQ to SQL en Visual Studio
  3. se le olvidó preparar el auto identidad a su mesa
  4. se fijó que al ir a su base de datos y el establecimiento de la auto-identidad
  5. Pero se olvidó de volver a crear/actualizar el contexto de LINQ a SQL DB !!!

: D

+0

¡Exactamente lo que era! – joshmcode

+0

usted hizo mi día :) –

+0

¡Gracias! Estaba golpeando mi cabeza contra exactamente este juego en LinqPad. –

0

que estaba teniendo el mismo problema.

Mi solución fue hacer manualmente la identidad de la columna INT en un NULL INT? columna en el diseñador de DBML, no en la tabla real de la base de datos, por supuesto. También establece el DbType en NULL en lugar de NOT NULL. Como tal:

[Column(Storage="_TestID", AutoSync=AutoSync.OnInsert, DbType="Int NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] 
public int? TestID 

Esto funciona con todas las operaciones DB. Al insertar simplemente establecer la columna de identidad a NULL en lugar de 0.

0

mi caso, me olvidé de actualizar mi archivo dbml después de configurar la columna Id a la identidad.