2009-03-12 13 views
6

Sto usando Linq su SQL. Ho un DataContext contro cui sono .SubmitChanges() 'ing. C'è un errore inserendo il campo di identità: Linq to SQL: perché ottengo errori IDENTITY_INSERT?

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

L'unico campo di identità è "ID", che ha un valore pari a 0. E 'definita nel DBML come:

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

Ci sono alcuni stranieri chiavi e ho verificato che hanno valori che si adattano al contenuto delle tabelle esterne.

Perché dovrei ricevere questo errore?

Edit: Ecco la domanda:

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 

Chiaramente si sta passando uno zero, nonostante sia mai stato assegnato un valore.

Edit: L'aggiunta di codice:

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(); 
} 

Inoltre, ho notato che quando aggiorno una piattaforma (InsertOnSubmit) esistente, non aggiorna. Profiler non mostra nemmeno le query eseguite.

+0

È possibile includere il codice in cui si crea l'oggetto e aggiungerlo a DataContext? – Portman

+0

I secondo Portman, si prega di inserire il codice che si sta utilizzando per l'inserto, vedere la mia risposta, è probabile che il problema sia lì – eglasius

risposta

7

Il codice imposta esplicitamente il valore ID a 0? (invece di lasciarlo intatto).

Aggiornamento 1: Come è stato pubblicato sulla versione aggiornata, linq2sql sta chiaramente passando il valore al db. Ecco uno che non ho avuto alcun problema con:

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

ho appena visto un altro, ed ha la stessa definizione esatta di quello che si sta utilizzando.

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

Aggiornamento 2: Per quanto riguarda gli aggiornamenti, non si dovrebbe fare InsertOnSubmit per questo. Basta aggiornare i valori e chiamare .SubmitChanges (dovrebbe essere lanciata un'eccezione). Nell'inserto è davvero strano, dato che gli attributi di proprietà che hai pubblicato sembrano essere corretti, quindi il metodo di inserimento che linq2sql genera dovrebbe essere corretto. Vorrei provare, ri-aggiungere nuovamente la tabella al designer e verificare che tutte le proprietà siano corrette.

Si noti che il metodo di inserimento generato dovrebbe essere simile (con un matchingRig_Insert):

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

this.Rig_Insert (/ * mucchio di valori * /, ref P1); obj.Id = p1.GetValueOrDefault(); }

+0

Tranne che la seconda definizione ha "IsPrimaryKey = true", aggiunta ad essa. – Chris

+0

@Chris, ho detto che la definizione di Samed è quella che sta usando;) – eglasius

+0

@Freddy, scusa la mia ignoranza, sono stanco dal lavoro, come sono gli stessi? – Chris

1

Se si forniscono il valore della colonna IDENTITY, è necessario aggiungere

SET IDENTITY_INSERT ON 

prima di istruzioni SQL, e

SET IDENTITY_INSERT OFF 

dopo per spegnerlo. Questo vale per QUALSIASI SQL grezzo.Se è stato utilizzato LINQ per creare un oggetto come:

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

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

Credo che funzionerà, mi perdoni se ho le classi sbagliate. Hai un'idea di base.

Edit: Oops .. Siamo spiacenti, non ha letto tutta la questione, io lo prendo indietro, stanco e affaticato dal lavoro ...

+0

non lo fa apposta, ciò farebbe sì che inserisca 0 ... quindi fallisce inserendo duplicati – eglasius

1

sembra che il tuo ID viene assegnato da qualche parte (anche se solo per inadempiente 0) - ti piacerebbe pubblicare un po 'del tuo codice LINQ?

2

Verificare che la proprietà Valore generato automaticamente nel dbml per quella colonna sia impostata su true. In caso contrario, LINQ tenterà di impostare il valore predefinito in base al tipo.

10

La mia teoria di quello che è successo è la seguente:

  1. È progettato e creato il database
  2. si è creato il contesto DB usando LINQ to SQL in Visual Studio
  3. Hai dimenticato di impostare l'auto- identità al tuo tavolo
  4. Hai risolto il problema andando al DataBase e impostando l'identità automatica
  5. Ma hai dimenticato di ricreare/aggiornare il tuo contesto LINQ TO DB DB !!!

: D

+0

Esattamente quello che era! – joshmcode

+0

hai reso la mia giornata :) –

+0

Grazie! Stavo sbattendo la testa contro esattamente questo scherzo in LinqPad. –

0

stavo avendo lo stesso identico problema.

La mia soluzione era quella di rendere manualmente la colonna identità INT in un valore Null INT? colonna nella progettazione DBML, non nella tabella effettiva del DB, naturalmente. Inoltre, imposta DbType su NULL anziché NOT NULL. Così:

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

Funziona con tutte le operazioni DB. Quando si inserisce semplicemente imposta la colonna Identity su NULL anziché su 0.

0

il mio caso, ho dimenticato di aggiornare il mio file dbml dopo aver impostato la colonna Id come identità.