2009-03-12 10 views
6

Ich benutze Linq zu SQL. Ich habe einen DataContext, gegen den ich .SubmitChanges() 'ing bin. Es ist ein Fehler, das Identitätsfeld Einfügen: Linq zu SQL: Warum erhalte ich IDENTITY_INSERT Fehler?

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

Die einzige Identitätsfeld ist „ID“, die einen Wert von 0. Es ist in der DBML definiert ist als:

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

gibt es ein paar ausländische Schlüssel, und ich habe überprüft, dass sie Werte haben, die mit dem Inhalt der fremden Tabellen übereinstimmen.

Warum sollte ich diesen Fehler bekommen?

Edit: Hier ist die Abfrage:

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 

Offensichtlich ist es eine Null vorbei, obwohl nie ein Wert zugewiesen wurde.

Edit: Hinzufügen von Code:

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

Auch merke ich, dass wenn ich eine bestehende rig (InsertOnSubmit) AKTUALISIEREN, es nicht aktualisiert. Profiler zeigt nicht einmal an, dass Abfragen ausgeführt werden.

+0

Können Sie den Code einfügen, in dem Sie das Objekt erstellen, und es dem DataContext hinzufügen? – Portman

+0

Ich zweite Portman, bitte posten Sie den Code, den Sie für den Einsatz verwenden, siehe meine Antwort, es ist wahrscheinlich das Problem ist dort – eglasius

Antwort

7

Ist Ihr Code den ID-Wert explizit auf 0 gesetzt? (anstatt es unberührt zu lassen).

Update 1: Wie Sie auf die aktualisierte Version geschrieben haben, übergibt linq2sql eindeutig den Wert an die db. Hier ist ein ich keine Probleme mit gehabt haben:

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

ich nur noch einen gesehen, und es hat die gleiche genaue Definition der von Ihnen verwendete.

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

Update 2: Im Hinblick auf Updates, Sie sind nicht tun InsertOnSubmit dafür soll. Aktualisieren Sie einfach die Werte und rufen Sie .SubmitChanges auf (sollte eine Ausnahme auslösen). Auf der Einfügung ist es wirklich seltsam, da die von Ihnen geposteten Eigenschaftenattribute korrekt zu sein scheinen, also sollte auch die von Linq2sql erzeugte Insert-Methode korrekt sein. Ich würde versuchen, die Tabelle erneut auf dem Designer hinzuzufügen und zu überprüfen, ob alle Eigenschaften korrekt sind.

Hinweis, dass die erzeugte Insert-Methode aussehen sollte (mit matchingRig_Insert):

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

this.Rig_Insert (/ * Bündel Werte * /, ref p1); obj.Id = p1.GetValueOrDefault(); }

+0

Mit Ausnahme der zweiten Definition hat "IsPrimaryKey = True" hinzugefügt. – Chris

+0

@Chris, ich sagte die samed Definition als die, die er verwendet;) – eglasius

+0

@Freddy, entschuldige meine Ignoranz, ich bin müde von der Arbeit, wie sind sie gleich? – Chris

1

Wenn Sie den Wert der Identity-Spalte liefern, müssen Sie

SET IDENTITY_INSERT ON 

vor Ihrer SQL-Anweisungen, und

SET IDENTITY_INSERT OFF 

nachdem es auszuschalten hinzuzufügen. Das gilt für jede RAW-SQL.Wenn Sie LINQ verwendet, um ein Objekt wie zu erstellen:

Ich glaube, das wird funktionieren, vergib mir, wenn ich Klassen falsch habe. Sie bekommen die Grundidee.

Edit: Oops .. Sorry, nicht die ganze Frage lesen, ich nehme es zurück, müde und erschöpft von der Arbeit ...

+0

er tut es nicht absichtlich, das würde dazu führen, dass es 0 einfügen ... dann scheitern für doppelte Einsätze – eglasius

1

scheint, wie Ihre ID irgendwo zugeordnet wird (wenn auch nur in Verzug zu 0) - möchten Sie etwas von Ihrem LINQ-Code veröffentlichen?

2

Stellen Sie sicher, dass die Eigenschaft Auto Generated Value in Ihrem dbml für diese Spalte auf true festgelegt ist. Wenn nicht, wird LINQ versuchen, den Wert basierend auf dem Typ festzulegen.

10

Meine Theorie von dem, was passiert ist, ist wie folgt:

  1. Sie entworfen und erstellt die DataBase
  2. Sie erstellt die DB Context LINQ in Visual Studio SQL
  3. Sie die auto- setzen vergessen Identität zu Ihrem Tisch
  4. Sie festgelegt, dass von
  5. zu Ihrer Datenbank und die Einstellung der auto-Identität gehen Aber Sie vergessen Ihre LINQ to SQL-DB-Kontext neu zu erstellen/aktualisieren !!!

: D

+0

Genau was es war! – joshmcode

+0

Sie machten meinen Tag :) –

+0

Vielen Dank! Hämmerte meinen Kopf gegen genau dieses Herumalbern in LinqPad. –

0

ich genau das gleiche Problem haben wurde.

Meine Lösung bestand darin, die Identität INT Spalte manuell in eine nullbare INT? Spalte im DBML-Designer, nicht in der tatsächlichen Tabelle der DB natürlich. Auch setzen Sie den DbType zu NULL statt NOT NULL. Wie folgt:

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

Dies funktioniert mit allen DB-Operationen. Wenn Sie einfach einfügen, setzen Sie die Identitätsspalte auf und nicht auf 0.

0

Mein Fall, ich habe vergessen, meine dbml-Datei nach der Id-Spalte Identität zu aktualisieren.