Laden...

UPDATE mit einer Spalte 'Plan' läuft auf Fehler

Erstellt von Seebär vor 12 Jahren Letzter Beitrag vor 12 Jahren 3.582 Views
S
Seebär Themenstarter:in
48 Beiträge seit 2011
vor 12 Jahren
UPDATE mit einer Spalte 'Plan' läuft auf Fehler

verwendetes Datenbanksystem: MS SQL SERVER 2008

Guten morgen,

ich lade Tabellen aus einer DB in ein DataTable und binde dieses an eine DataGridView.

Der User kann beliebige Änderungen vornehmen.

Diese werden dann mittels Knopfdruck an die DB überspielt.

Das klapp soweit auch schon sehr gut.

Nur bei einer Tabelle laufe ich auf einen Fehler.

Diese hat eine Spalte namens 'PLAN'.

Der Fehler läßtsich wie feolgt reproduzieren:

Server-Seite:


CREATE TABLE [dbo].[Test](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Plan] [nvarchar](29) NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

INSERT INTO Test
VALUES
('Ein Wert'),
('Noch ein Wert')

Client-Seite:


            public static void PlanError()
            {
                int changedRows = 0;
                OleDbCommand cmd = new OleDbCommand();
                OleDbConnection con = new OleDbConnection(@"Provider=SQLOLEDB.1;Data Source=server11;Integrated Security=SSPI;Initial Catalog=<Datenbankname>");                
                cmd.Connection = con;
                cmd.CommandText = "SELECT * FROM Test";

                OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);                
                DataTable dataTable = new DataTable();

                try
                {
                    adapter.Fill(dataTable);
                    DataRow dataRow = dataTable.NewRow();
                    // einen neuen Wert einfügen
                    dataRow["Plan"] = "Ganz neuer Wert";
                    dataTable.Rows.Add(dataRow);

                    OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
                    changedRows = adapter.Update(dataTable);
                }
                catch (Exception ex)
                {
                   System.Windows.Forms.MessageBox.Show(ex.Message);
                }
            }

Führt man die Methode 'PlanError' aus, so kommt folgende Fehler:> Fehlermeldung:

Falsche Syntax in der Nähe des 'Plan'-Schlüsselworts.

Das vom CommandBuilder erzeugte Insert-Statement lautet


INSERT INTO Test (Plan) VALUES (?)

Führe ich den SQL-Befehl im Management-Studio aus, z.B.


INSERT INTO Test (Plan) VALUES ('Ganz neuer Wert')

bekomme ich auch obigen Fehler.

Es funktioniert aber, wenn ich den Spaltennamen 'Plan' in eckige Klammern setze.


INSERT INTO Test ([Plan]) VALUES ('Ganz neuer Wert')

Leider erzeugt der OleDbCommandBuilder das Insert-Statement ohne diese eckigen Klammern.

Deswegen meine Frage: Gibt es irgendwelche Einstellungen, die den OleDbCommandBuilder die Spaltennamen in eckige Klameern zu setzen?

Oder gibt es einen anderen Ansatz, das Problem zu lösen?

Die Tabellenstruktur und damit die Spaltenbezeichner sind vorgegeben und können nicht geändert werden.

Ich bin für jede Anregung dankbar!

S
24 Beiträge seit 2011
vor 12 Jahren

Warum der Fehler kommt weiß ich nicht. Reproduzieren ließ er sich. (Auch wenn man das Insertstatement manuell setzt.)

Wenn du aber anstelle von OleDb System.Data.SqlClient nutzt, klappt alles.

1.552 Beiträge seit 2010
vor 12 Jahren

Hallo Seebär,

du verwendest Reservierte Schlüsselwörter. Dies kann wie du siehst in die Hose gehen.
Bitte verwende diese NIE. Um jedoch Reservierte Schlüsselwörter verwenden zu können musst du wie du selbst herausgefunden hast die betroffene Spalte in [...] setzen.

Für eine Liste der Reservierten Schlüsselwörter siehe:
Reservierte Schlüsselwörter

p.s. auch in C# kann man eine Variable int nennen. Dies würde man dan

int @int = 5;
double @double = 4d;
double @if = @double + @int;

aber dies macht man einfach nicht. Dasselbe ist in SQL.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

S
Seebär Themenstarter:in
48 Beiträge seit 2011
vor 12 Jahren

Danke ersteinmal für die Antworten!

@Schleifer:

Mit dem Sql-Client bekomme ich irgendwie keine Verbindung zur Datenbank hin. Der SQL Server sowie alle Datenbanken liegen auf einen anderen Server.

Vielleicht habe ich da auch noch eine Wissenslücke.

Mein Connectionstring via OleDB lautet ja


OleDbConnection con = new OleDbConnection(@"Provider=SQLOLEDB.1;Data Source=server11;Integrated Security=SSPI;Initial Catalog=<Datenbankname>");

Wie müsste er denn für den Sql-Client lauten? Dan kann ich ja keinen Provider angeben...

@xxMUROxx:

Das mit den Schlüsselwörtern ist mir schon klar. Aber auf die Namensgebung der Tabellenspalten habe ich keinen Einfluss; sie kommen von extern und dürfen nicht geändert werden.

Und der Caommand-Builder generiert die INSERT-, DELETE- und UPDATE-Statements automatisch, so dass ich da leider auch nicht eingreifen kann.

Oder gibt es doch etwas, was ich ihm mitgeben kann, damit er die Feldnamen in exkige Klammern setzt?

Ich wollte mir eigentlich ersparen, die drei Kommandos selber zu schreiben - bis auf diesen blöden Fehler klappt ja der update-Befehl des Adapters vorzüglich!

V
66 Beiträge seit 2010
vor 12 Jahren

Helfen Dir die Eigenschaften QuotePrefix resp. _QuoteSuffix _weiter?

1.552 Beiträge seit 2010
vor 12 Jahren

Wie müsste er denn für den Sql-Client lauten?

Am einfachtsten geht es mit den von DbConnectionStringBuilder erbenden Klassen bzw mit ConnectionString.com

Mit dem Sql-Client bekomme ich irgendwie keine Verbindung zur Datenbank hin.

Wie lautet der Fehler bzw Fehlercode?

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

S
Seebär Themenstarter:in
48 Beiträge seit 2011
vor 12 Jahren

@vagtler:

Die Eigenschaften hören sich schon interessant an.

Laut Hilfe gehören diese der Klasse SqlSyncAdapterBuilder an.

Kann ich diese denn überhaupt in meiner OleDB-Umgebung verwenden?

Und wenn ja, wie?

1.564 Beiträge seit 2007
vor 12 Jahren

Wie müsste er denn für den Sql-Client lauten? Dan kann ich ja keinen Provider angeben...

So:


SqlConnection con = new SqlConnection(@"Data Source=server11;Integrated Security=SSPI;Initial Catalog=<Datenbankname>");

Mit dem Sql-Client bekomme ich irgendwie keine Verbindung zur Datenbank hin. Der SQL Server sowie alle Datenbanken liegen auf einen anderen Server.

Wenn du mit OLEDB drauf kommst, kommst du garantiert auch mit dem nativen SQL Provider drauf.

Zu deinem eigentlichen Problem:
Der XYZCommandBuilder ist ein echter Performance-Killer, da er immer wieder die Tabellen-Informationen vom Server abfragen muss, bevor er die Commands erzeugen kann.
Verwende entweder einen O/R-Mapper, oder verwende Stored Procedures.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

S
Seebär Themenstarter:in
48 Beiträge seit 2011
vor 12 Jahren

Tatsächlich, das hat nun super geklappt - und jetzt funktioniert auch das Update!

Scheint tatsächlich ein kleiner Bug in der OleDB-Umgebung zu sein...

O/R-Mapper ist Neugebiet für mich - hast Du vielleicht Quellen / Links, wo ich mich einlesen könnte?

Danke euch allen für die Hilfe!!

1.552 Beiträge seit 2010
vor 12 Jahren

Entity Framework
NHibernate

Aber ich denke eine Suche in google hätte dies auch ergeben. Wir sind nämlich auch kein Linkgenerator

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

F
10.010 Beiträge seit 2004
vor 12 Jahren

@Seebär:
Ja, ist ein Bug, F40 genannt.
Der Fehler der ca 40cm vor der Tastatur sitzt.

Wenn DU reservierte Wörter im Sql Benutzt, gibt es halt Fehler, und der OleDbAdapter ( wie alle DataAdapter ) bietet dir ja an, die Namen zu maskieren.

@Florian Reischl:
Seit wann sind ORMapper schneller als ein CommandBuilder?
Und SP sind nicht schneller als (richtig ) parametrisierte Queries.
Was bei mehreren Datensätzen die Zeit kostet ist die meist fehlende Transaction.

1.564 Beiträge seit 2007
vor 12 Jahren

Hi FZelle

@Florian Reischl:
Seit wann sind ORMapper schneller als ein CommandBuilder?
Und SP sind nicht schneller als (richtig ) parametrisierte Queries.
Was bei mehreren Datensätzen die Zeit kostet ist die meist fehlende Transaction.

Kommt natürlich immer auf die Verwendung an, aber normalerweise cached ein O/R-Mapper die Tabellendefinitionen, bzw. lädt sich diese aus entsprechenden Mapping-Files auf dem Client. Der CommandBuilder cached nix, jede einzelne Verwendung führt wieder zu einem unnötgen Server-Roundtrip um die Spalteninformationen abzufragen.

Ich hatte nicht gesagt, dass Prozeduren schneller sind. Ich sage nur, entweder ORM oder SPs. Nicht wegen der Geschwindigkeit, sondern weil ich von im Client zusammengebaute SQL Statements nichts halte wenn's nicht ordentlich gekapselt (unt getestet!) ist.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.