Laden...
Avatar #avatar-2880.jpg
Florian Reischl myCSharp.de - Experte
Softwarearchitekt, Technischer Projektleiter München Dabei seit 16.10.2007 1.564 Beiträge
Benutzerbeschreibung

Forenbeiträge von Florian Reischl Ingesamt 1.564 Beiträge

29.08.2011 - 13:02 Uhr

Hi Equilibrium

Tipp zum Suchen, Microsoft eine MSDN Lizenz für Schüler und Studenten (und Lehrer) die vielleicht deinen Anforderungen entspricht.

Grüße
Flo

29.08.2011 - 12:41 Uhr

Hi

Würde ich über ein NOT EXISTS machen:


SELECT
   k.*
FROM Kunden k
WHERE NOT EXISTS (
   SELECT *
   FROM Produkte p
   WHERE k.Id = p.KundenId
      AND p.Sparte = 10
   );

Weil die wenigsten Daten angelangt werden müssen und nichts aggregiert wird.

Gehen würde theoretisch auch ein LEFT JOIN mit DISTINCT:


SELECT DISTINCT
   k.*
FROM Kunden k
   LEFT JOIN Produkte ON k.Id = p.KundenId AND p.Sparte = 10
WHERE p.KundenId IS NULL

Allerdings führt der (full) LEFT JOIN ggf. dazu dass mehr Daten angelangt werden und der DISTINCT zu einem nicht zu unterschätzendem "Distinct Sort".

Grüße
Flo

29.08.2011 - 12:11 Uhr

Hallo m.grauber

Das ist grundsätzlich natürlich möglich, aber...

Frage:
Wenn du in deinem Ergebnis "Produkte.Produkt" zurücklieferst, welches soll denn dann zurückgeliefert werden? Das jüngste? Das älteste? Das grünste?

Grüße
Flo

29.08.2011 - 10:16 Uhr

Hallo manunidi

Geht doch trotzdem.


SELECT *
FROM Foo
WHERE BeginnDatum BETWEEN @from AND @to
   AND EndDatum BETWEEN @from AND @to

Grüße
Flo

27.08.2011 - 20:21 Uhr

Hi

Das geht nicht wirklich über ein Statement, aber du kannst dir die Werte mit einem UNION ALL zusammenhängen und auf einmal zurückliefern lassen.



DECLARE @T TABLE (
   Id INT NOT NULL PRIMARY KEY CLUSTERED
);

INSERT INTO @T
             SELECT 1
   UNION ALL SELECT 2
   UNION ALL SELECT 3
   UNION ALL SELECT 4
   UNION ALL SELECT 5
   UNION ALL SELECT 6
   UNION ALL SELECT 7;

DECLARE @from INT, @to INT;
SELECT @from = 3, @to = 5;

; WITH 
prev_row AS (
   SELECT TOP(1) *
   FROM @T
   WHERE Id < @from
   ORDER BY Id DESC
),
next_row AS (
   SELECT TOP(1) *
   FROM @T
   WHERE Id > @to
   ORDER BY Id
)
SELECT * FROM @T WHERE Id BETWEEN @from AND @to
UNION ALL
SELECT * FROM prev_row
UNION ALL
SELECT * FROM next_row 
ORDER BY Id;

Grüße
Flo

26.08.2011 - 17:41 Uhr

Hi

Gerade ist mir in deiner Prozedur noch was aufgefallen, du hast in Zeile 72 ein RETURN. Damit hebelst du dir ggf. dein Transaction-Handling aus. Das kann übrigens auch dein Problem sein, da .NET implizit eine Transaktion erzeugt, wenn keine existiert.

Zum SQL:
Ich meinte so was. Habe die DELETE-Zeilen auskommentiert und durch SELECT's drüber gepackt, da ich keine Daten habe kann ich natürlich nur vermuten dass das ich's richtig interpretiert habe.


ALTER PROCEDURE [dbo].[DeleteBankTransfersFromClearing]
(
   @clearingId int
)
AS BEGIN
   DECLARE @isTrans   bit;
      
   IF @@TRANCOUNT>0   
      SET @isTrans = 1;
   ELSE 
      SET @isTrans = 0;

   BEGIN TRY
      IF @isTrans=0 
      BEGIN TRANSACTION
         --] Ab hier individueller Code:   [--
         DECLARE @affected INT;
         SET @affected = 0;
         
         -- temp table to catch all bankTransfer ids to be delete
         DECLARE @transfers_to_delete TABLE (Id INT NOT NULL PRIMARY KEY CLUSTERED);
         
         -- get bankTransfer ids to be deleted
         -- (remove the DISTINCT if id_banktransfer is unique in clearing_banktransfer)
         INSERT INTO @transfers_to_delete
         SELECT DISTINCT cb.id_banktransfer
         FROM clearing_banktransfer cb
            INNER JOIN clearing_debitor_invoice cdi on cdi.id = cb.id_clearing
            INNER JOIN clearing_debitor cd on cd.id = cdi.id_clearing_debitor
         WHERE cd.id_clearing = @clearingId;
         
         -- count rows affected
         SET @affected = @@ROWCOUNT;
         
         
         --  delete clearing_bankTransfer rows
         SELECT cb.*
         --DELETE cb
         FROM clearing_banktransfer cb
         WHERE EXISTS (
            SELECT * 
            FROM @transfers_to_delete del 
            WHERE cb.id_bankTransfer = del.id);
         
         -- count rows affected
         SET @affected = @affected + @@ROWCOUNT;
         
         -- delete bankTransfer rows
         SELECT bt.*
         --DELETE bt
         FROM bankTransfer bt
         WHERE EXISTS (
            SELECT *
            FROM @transfers_to_delete del 
            WHERE cb.id_bankTransfer = del.id);
         
         -- count rows affected
         SET @affected = @affected + @@ROWCOUNT;

         IF (@affected = 0)
            SELECT 'No data!';

         --] Ende individueller Code [--
      IF @isTrans=0       
      COMMIT TRANSACTION
      return 0

   END TRY
   BEGIN CATCH
      EXECUTE GetErrorInfo;
      IF @isTrans=0
      ROLLBACK TRANSACTION
      RETURN (-1)*ERROR_NUMBER()   -- negative Errorcodes
   END CATCH
END

Grüße
Flo

26.08.2011 - 16:47 Uhr

CURSOR und LOOPs sind in SQL Server fast äquivalent langsam, wobei die Schleife meistens minimal schneller ist. Ich würde das Statement so umbauen, dass komplett sequenziell, ohne Schleifen und IF-Konstrukte gearbeitet wird. Dann gibt's auch keine Probleme mit Execution Plan Caching.

Zu deinem eigentlichem Problem (weil's ja wohl über's SSMS schnell ist):
Hast du mal im Profiler geschaut?

Grüße
Flo

26.08.2011 - 15:38 Uhr

Hi

Nachdem es hier erstmal nicht um SQL geht (sonst würde ich definitiv empfehlen die Schleife rauszuschmeißen 😉), hänge ich mich an dN!3L an, schau dir mal an was der Profiler anzeigt.

RECOMPILE ist zwar gefährlich, kann durch die IF-Statements wirklich helfen.

Grüße
Flo

24.08.2011 - 20:40 Uhr

Hallo Campy

Nein, du legst in deiner DB nicht den Code ab. Wäre erstens nur eine Frage der Zeit, dass ihm sich jemand anschaut und ggf. klaut/ändert. Zweitens würde es sehr viel unnötigen CPU Auslastung kosten, wenn jeder Client/Service sich das Zeug erstmal kompilieren müsste. Drittens kannst du dir sicher sein, dass du in teufels Küche kommst um immer alle nötigen Referenzen der jeweiligen Module zusammenzubringen um dann kompilieren zu können.

Lege, wie gfoidl auch schreibt, entweder die Binaries in die DB oder verweise auf Ordner im File-System.

Grüße
Flo

24.08.2011 - 18:20 Uhr

Hallo Campy

Doch, du bist nicht der Erfinder dieses Rades 😉

Das ganze ist nur nicht einfach zu bauen und noch weniger einfach kontrollierbar zu halten.

gfoidl hat dir den nötigen Ansatz für die Verwaltung der Funktionalität gegeben, nähmlich ein Plugin-System. Ich habe dir den Ansatz für ein flexibles Datenmodell gegeben.

Damit kannst du dir dein System so aufbauen wie du es beschrieben hast.

Grüße
Flo

24.08.2011 - 13:10 Uhr

Hallo Rahvin

Wenn du deine Foreign-Keys definiert hast kann die referenzelle Integrität nicht verletzt werden. Du bekommst beim Versuch den Datensatz zu löschen eine Exception.

Möglichkeit 1:
Du kannst die Exception abfangen und einen Fehler "Datensatz kann nicht gelöscht werden" ausgeben.

Möglichkeit 2:
Du kannst den Foreign Key so definieren, dass kaskadierend gelöscht wird - bitte aber mit Vorsicht behandeln.

Möglichkeit 3:
Du prüfst selbst in deiner Anwendung ob referenzierende Daten bestehen und (a) löschst sie oder (b) verhinderst das löschen.

Grüße
Flo

24.08.2011 - 13:06 Uhr

letzendlich kann ich mich damit jedoch nicht anfreunden, da ich da nicht die möglichkeit habe typisiert zu Arbeiten (DataSets,Tables, Rows )

Typisierte DataSets sind nicht wirklich typisiert. Das sind nur Property-Fassaden auf eine untypisierte DataRow (sorry Bernd, nur meine Meinung 😉 ).

Allerdings kannst du das DataSet ja mit jedem beliebigen DB Provider, also natürlich auch dem nativen MySQL Provider, verwenden.

@Bernd:
Hi 😃
Ich glaube es geht b.wayne um eine Designer-Unterstützung um das typisierte DataSet mit dem MySQL Provider zu verheiraten. Da bin ich blank, vielleicht kannst du da aber weiterhelfen.

Grüße
Flo

24.08.2011 - 11:27 Uhr

Hi Nitro2k7

Dennoch würde ich gern bezüglich der Aussage rein aus Interesse wissen: Warum rätst du davon ab?

Technisch, weil jede Verwendung des CommandBuilders zu einer unnötigen Abfrage auf die Datenbank führt (siehe dazu meinen Post in dem anderen Thread.).

Ansonsten bin ich kein Freund von Client-Anwendungen die sehr SQL nah arbeiten. Ich finde es sauberer, entweder einen O/R-Mapper zu verwenden oder aber wirklich auf Stored Procedures zu setzen.

Grüße
Flo

24.08.2011 - 11:13 Uhr

Hallo b.wayne

Ein sehr ähnliches Thema hatten wir gerade erst:

UPDATE mit einer Spalte &#39;Plan&#39; läuft auf Fehler

Wenn du auf den nativen MySQL Provider wechselst dürfte der Command-Builder funktionieren.

Grundsätzlich rate ich aber vom Command-Builder ab.

Grüße
Flo

24.08.2011 - 11:04 Uhr

Hi

ADO.NET DbContext Generator V4.2

ADO.NET Self-Tracking Entity Generator

ADO.NET POCO ENTITY GENERATOR lol! Soviel zum "Standard"...

@ZeroQool:
Wie Abt schon richtig gesagt hat (sorry, für mein Unwissen zu den Features des EDMX Designers), man kann im Designer "Default Values" für Scalar Properties angeben. Bei mir werden die dann auch automatisch in die erzeugen Entity-Classes eingefügt. Wenn das bei dir nicht so ist würde ich evtl. versuchen auf ein anderes T4 Template zu wechseln.

Grüße
Flo

24.08.2011 - 10:07 Uhr

Aber wenn ich die History im Source Control anschaue, dann habe ich bisher nur mit virtuellen Relationen gearbeitet.

Der Artikel scheint out-of-date zu sein. Habe es jetzt auch gerade mal getestet (T4 Template "ADO.NET Self-Tracking Entity Generator"). Bei dem Template werden Properties nicht virtual, dafür bekommen die Entitäten bei dem Template die Interfaces IObjectWithChangeTracker, INotifyPropertyChanged. Ist mir bislang nicht aufgefallen, weil ich meine Entitäten normalerweise aus einem anderen Tool erzeuge.

Ich glaube ich muss mir das bei Gelegenheit (und schlechterem Wetter) mal genauer anschauen.

Grüße
Flo

24.08.2011 - 09:44 Uhr

Hi herbivore

Leider gibt es im Framework keine GUI-neutrale Tree(Node)-Klasse.

Da fällt mir spontan der generische Mini-Tree vom ErfinderDesRades ein:

public class MyTreeNode : List<MyTreeNode>
{
    public string Foo { get; set; }
    public string Bar { get; set; }
}

😉

Grüße
Flo

24.08.2011 - 09:23 Uhr

Hi Abt!

virtual wird eigentlich nur für die Relations benötigt - nicht für die "Properties" an sich. So wirds auch vom Visual Studio "EDMX => POCO Entity Generator" erstellt.

Soviel ich weiß benötigt EF virtual Properties für alle Datenfelder um ein effizientes Change-Tracking in den, zur Laufzeit erzeugten, Proxy-Objekten anzubieten. Sonst muss EF immer alle Werte/Relationen beim Save durchlaufen und mit den Ausgangswerten zu vergleichen. Die virtual Relationen zu anderen Entitäten wird zusätzlich noch für Lazy-/Deferred-Loading verwendet.
Quelle: POCO in the Entity Framework : Part 2 – Complex Types, Deferred Loading and Explicit Loading. Kann aber natürlich sein, dass das evtl. nicht mehr aktuell ist. Allerdings wäre dann Change-Tracking/Lazy-Loading für POCOs fast nur noch über einen Weaver zu realisieren.

Dieser erstellt nebenbei auch einen Constructor, in dem alle Properties ihren Standard-Wert erhalten.

Danke für die Info. Das wusste ich nicht mehr 😃.

Signatur:
speed is a feature

Dickes +1! Ist mir gerade erst aufgefallen. Wird viel zu oft unterschätzt/vergessen.

24.08.2011 - 08:59 Uhr

Und was hindert dich daran die im Constructor zu setzen? Die virtual Properties braucht EF für Lazy-Loading und Change Tracking.

Allerdings, wenn ich's mir so recht überlege, würde ich die Erzeugung neuer Entitäten eh in eine entsprechende Factory-Methode kapseln, dann gibt's sicher keine Probleme.

Grüße
Flo

24.08.2011 - 08:51 Uhr

Umm... Wie wär's mit dem Constructor?


public class MyPocoEntity
{
    public MyPocoEntity()
    {
        FirstName = "John";
        LastName = "Doe";
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Grüße
Flo

23.08.2011 - 22:45 Uhr

Hi Holgie

Zu ODP:
Wir verwenden bei uns ebenfalls Oracle in einem Projekt und wir verwenden den Oracle .NET Provider schon seit ein paar Jahren. Schau mal hier:
Oracle Data Provider for .NET
(Ich weiß natürlich nicht welche Oracle Version ihr habt, aber vielleicht funktioniert's ja.)

Zu der Exception:
Das sieht bitter aus. Ich befürchte da kannst du nicht viel machen. Die Meldung kenne ich noch aus alten C/C++ Zeiten. Bedeutet normalerweise das irgendwo ein Pointer überschrieben wurde und ins Nirvana zeigt.

Das einzige das mir einfällt, was du evtl. noch selber machen könntest, ist:
Prüfe mal ob ihr neue Datentypen verwendet, die ihr vorher nicht verwendet habt. Kann sein dass der ODBC Treiber damit nicht klar kommt.
Prüfe auch mal ob der Server und/oder die installierte Oracle-DB, die ersten x64 Kisten sind.

Wenn's das nicht ist weiß ich leider auch nicht weiter

Viel Glück
Flo

23.08.2011 - 22:12 Uhr

Hi

Bin zwar nochmal der gleiche, aber ich hoffe das ist okay 😉

Noch jemand eine Idee wie man das flexibel gestalten kann? (kundenspezfisch mit dem gleichen Ausgangsprodukt)

Okay, das hört sich jetzt nach was anderem an als vorher. Wenn's darum geht ein Ausgangsprodukt in die Lage zu versetzen beliebige, zusätzliche Felder/Daten zu verarbeiten kannst du entweder XML Spalten in deiner Datenbank verwende (bin ich aber nicht überzeugt von) oder du schaffst einen EAV/CR Database Hybriden um deine Ausgangstabellen nach belieben zu erweitern.

Grüße
Flo

23.08.2011 - 22:07 Uhr

Hi

Steve Jones (Twitter), Admin von SQLServerCentral.com, hat gerade nochmal darauf hingewiesen. Microsoft's neuer SQL Server 11, Codename "Denali", kommt nächstes Jahr raus.

Microsoft hat ja schon länger gelernt wie wichtig die Communities sind, deswegen bittet Dan Jones (MSFT) um weitere Tester.

Steve's aktuellen Blog zum Thema: Help with testing Denali, SQL Server 11
Dan Jones' Blog zum Thema: Help Make SQL Server “Denali” The Best Release Yet!

Vielleicht hat ja hier noch jemand Zeit, Lust und freie Ressourcen um auch ein bisschen mitzutesten. (Lieber raucht einem eine Test-VM ab als eine produktive Kiste, oder? ;-P)

Danke und Grüße
Flo

23.08.2011 - 21:27 Uhr

Hallo Campy

Ja, dass gib's schon fertig. Du kannst z.B. den Entity Framework verwenden und das Standard-T4 File durch die POCO Code Generation austauschen. Du kannst dir auch selbst eine T4 Code-Generierung schreiben, da gibt's aber wirklich viele fertige im Netz.

Grüße
Flo

23.08.2011 - 20:16 Uhr

Du hat dir gerade fast die Antwort geliefert. Du definierst eine Paketgröße die jeder Client abholt, sagen wir 10MB. Kannst du aber natürlich auch von der Gesamtgröße der Datei abhängig machen - dann aber nicht vergessen ein Maximum zu setzen.

Die holen jetzt ihr Paket + die Info an welcher Stelle der Gesamtdatei dieses Paket eingefügt werden muss. Am Ende brauchst du einen Prozess der dass dann alles wieder zusammenführt.

Grüße
Flo

23.08.2011 - 19:56 Uhr

Hallo EnjoX

Ich bin mir zwar nicht 100% sicher wo dein Problem liegt, wenn es aber darum geht eine Datei gleichzeitig aus mehreren Threads zu öffnen, dann so:

FileStream stream = new FileStream(@"C:\sonstwas.txt", FileMode.Open, FileAccess.Read, FileShare.Read);

Grüße
Flo

23.08.2011 - 19:53 Uhr

Hallo mrennen

Bau dir einen eigenständigen Prozess als x86 Kompilat, der ohne große Logik das Excel-File öffnet und die Daten 1:1 in eine Staging-Tabelle lädt. Dann kann dein eigentlicher Prozess auf der Staging-Tabelle arbeiten, statt auf dem Excel-File.

Es gibt zwar noch die Office-COM Objekte, die du dir anschauen könntest. Die sind aber grottenlahm und, wenn ich mich nicht täusche, ebenfalls nur x86 kompatibel.

Grüße
Flo

23.08.2011 - 17:29 Uhr

Hallo frankey

Erzeuge in deiner Klasse kein neues TreeView, sondern erzeuge nur die Nodes, dann kannst du einfach die Root-Nodes an das TreeView in deiner Form anhängen.

Grüße
Flo

23.08.2011 - 17:17 Uhr

Hi

Wenn du eh dynamisch mit unterschiedlichen Ergebnissen arbeiten must, gib doch, wie FZelle schon geschrieben hat, z.B. die DataRow zurück. Da steckt alles drinnen.

Grüße
Flo

23.08.2011 - 17:14 Uhr

Hallo Holgie

Ich bin zwar echt kein Oracle Profi, aber zwei Dinge:

  1. Poste doch mal bitte die Exception die du bekommst.

  2. Warum denn ODBC? Das ist von vorvorgestern. Oracle bietet doch native .NET Data Provider. Ich kann mir gut vorstellen, dass der reine Wechsel auf den nativen Provider das Problem behebt.

Grüße
Flo

23.08.2011 - 17:07 Uhr

Das geht nicht. Funktionen/Prozeduren sind kompiliert und an ihre Objekte gebunden, nur weil du die Funktion aus einer anderen Datenbank ausführst werden trotzdem die Tabellen/Views aus der Datebank verwendet in der die Funktion/Prozedur liegt. Du könntest theoretisch versuchen mit dynamischem SQL in einer Prozedur was hinzufrickeln, aber das bleibt dann auch hingefrickelt. Und man muss mit dem Execution-Plan Caching aufpassen.

Grüße
Flo

23.08.2011 - 17:04 Uhr

Hi Abt,

Sorry für die späte Antwort, war heute stressig.

Die Frage ist hier auch der Aufwandsfaktor. Auf der Liste steht es - jedoch aktuell noch mit wenig Smileys dahinter 😉

Das müsstet ihr natürlich erstmal intern klären, ob es okay wäre wenn der IIS mal die Anwendung verschmeißt.

Das Problem des Monitorings bleibt weiterhin, wobei ich Monitoring hier als Überbegriff verwende.
Die von der IT zur Verfügung gestellte Software bietet uns nur Pings und andere Dinge "von außen" an bzw. Abfragen auf URI-Ebene

URL würde doch reichen. Wenn das Monitoring irgendwelche Skripte verwendet (PHP, Perl, PowerShell) - und Admins verwenden fast immer Skripte 😉, dann könntest du ein WsHttpBinding verwenden und über den Response einen Status zurückliefern.

Musst du immer wieder durch die ganzen Dateien um Änderungen (Owner/Last Update/Size/...) zu finden, oder brauchst du jede Datei [..]
[...]da diese Infos für Berechnungen in der Datenbank liegen müssen.

Okay, damit hast du meine Frage beantwortet. Wenn nicht eh schon hätte ich ebenfalls vorgeschlagen das Dateisystem so wenig wie möglich zu verwenden sondern alle Infos in eine DB zu schreiben. Da sind ein paar Hunderttausend Werte ja kein Problem.

Grüße
Flo

23.08.2011 - 10:15 Uhr

Hallo Abt

Gefühlsmäßig würde ich mich eher für Version 2 entscheiden, eben weil dann nichts verloren gehen kann.

Zu Monitoring/Administration:
Du könntest in dem Windows-Service ja einen WCF Service über TCP (oder sogar HTTP(S)) hosten, dann kannst du weiterhin alles von Remote machen.

Zusätzliche Frage:
Musst du immer wieder durch die ganzen Dateien um Änderungen (Owner/Last Update/Size/...) zu finden, oder brauchst du jede Datei immer nur wenn sie neu angelegt wird, bzw. sich ändert?

Grüße
Flo

22.08.2011 - 20:38 Uhr

Hi

...
WHERE (Tabelle1.Standort LIKE 'Maschine%') AND (Tabelle2.Description2='Rohstoff' OR Tabelle2.Description2 IS NULL)

So Versuch ich es gerade. Leider Gibt der Server keinen Mux von sich. Abfragedauer z.z. bei über 17min 😕

Wieso diese Abfrage lange dauert kann ich dir erklären. Dein "Spalte = 'Wert' OR Spalte IS NULL" nennt sich "Catch All Query" und führt bei SQL Server unweigerlich zu einem Full Index Scan. Hierzu: Catch-all queries. Da du mit einer EAV/CR Datenbankstruktur (Objekttabelle + Beschreibungstabellen) arbeitest bin ich mir sicher, dass deine Tabellen sehr viele Datensätze beinhalten, da dauert der Scan dementsprechend lange.

Zu dem SQL Statement würde ich meine 5 Cents, in einer abgewandten Form von IUndisposables Statement, reinwerfen:



; WITH t2 AS (
   SELECT
      ObjectName AS ObjectName
      ,MAX(CASE WHEN Tabelle2.Description2 = 'Rohstoff' THEN Tabelle2.Value ELSE NULL END) AS Rohstoff
      ,MAX(CASE WHEN Tabelle2.Description2 = 'Gewicht' THEN Tabelle2.Value ELSE NULL END) AS Gewicht
   FROM Tabelle2
   GROUP BY ObjectName
)
SELECT
   t1.ObjectName
   ,t2.Gewicht
   ,t2.Rohstoff
FROM Tabelle1 t1
   LEFT JOIN t2 ON t1.ObjectName = t2.ObjecdtName

Die CTE dürfte gerade bei sehr vielen JOINs auf die gleichen Tabellen schneller werden, musst du aber mal prüfen.

Grüße
Flo

22.08.2011 - 16:50 Uhr

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

22.08.2011 - 14:17 Uhr

Hallo zerberos

Meinst du so was:


Form parentForm = this.FindForm();
Form mdiParent = parentForm != null ? parentForm.MdiParent : null;

Grüße
Flo

22.08.2011 - 13:12 Uhr

Hi

Ich würde sicherheitshalber ein NOT EXISTS verwenden, da das vom SQL Server eigentlich immer als Left/Right-Semi Join ausgeführt wird.


SELECT Id
FROM T1
WHERE NOT EXISTS (
   SELECT Id
   FROM T2
   WHERE T1.Id = T2.Id
   )

Bei NOT IN(Sub-Query) habe ich schon öffter mal Probleme gehabt, weil SQL Server beschloss Nested auf Zeilenebene auszuführen.

Bei EXCEPT weiß ich jetzt aus dem Stehgreif nicht, ob der immer als Semi Join ausgeführt wird.

Grüße
Flo

22.08.2011 - 12:52 Uhr

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

22.08.2011 - 10:58 Uhr

Hallo Dirk

Also bei mir funktionierts einwandfrei. Hier ein Beispiel:



-- ///////////////////////////////////////////////
-- create UDF on tempdb
USE tempdb;
GO

CREATE FUNCTION udf_test()
RETURNS TABLE
AS
RETURN
   SELECT * FROM INFORMATION_SCHEMA.TABLES;
GO

-- ///////////////////////////////////////////////
-- switch to master and utilize the function on tempdb
USE master;
GO

-- returns tables with catalog "tempdb"
SELECT * FROM tempdb.dbo.udf_test();
GO

Grüße
Flo

20.08.2011 - 10:57 Uhr

Hallo Qualimbo

Visual Studio ist eine tolle IDE, aber wenn's um SQL Server Datenbanken gibt würde ich's mal zur Seite legen.

Besorg dir das SQL Server Management Studio Express runter, wenn nicht schon gemacht:
Microsoft SQL Server 2008 R2 RTM - Management Studio Express

Passe deinen Connection String so an, dass du nicht mehr mit AttachDbFilename arbeitest, sondern stattdessen den Server und die Datenbank angiebst. Beispiele hierzu findest du unter anderem hier:
SqlConnection.ConnectionString

Dann passieren solche Sachen, wie du beschrieben hast auch nicht mehr.

Grüße
Flo

19.08.2011 - 18:03 Uhr

Hi

Erstmal, danke dass du deine Lösung geteilt hast.

Hierzu aber zwei Anmerkungen:

1.
Fang gar nicht erst mit AttachDbFilename an. Das ist ein echtes Schmarn-Feature von SQL Express. Braucht keiner, bringt nix und macht nur Probleme - z.B. sehr langsame Verbidungen, keine gleichzeitigen Zugriffe, ...

2.
Lass die ArrayList in Frieden ruhen, die ist Legacy. Verwende die generische List<T>.

Grüße
Flo

19.08.2011 - 17:06 Uhr

Hi Qualimbo

Habe mir das Tutorial jetzt nicht wirklich angeschaut, aber klar kannst du im Nachhinein den Zielrechner, auf dem sich der SQL Server befindet anpassen.

Du hast hierfür einen Connection-String aller:

Data Source=RechnerName;Initial Catalog=DatenbankName;Integrated Security=SSPI;

Alles was zu tun ist, ist den Connection-String anzupassen. Falls du mit Windows-Authentifizierung arbeitest (Integrated Security oder Trusted_Connection), darauf achten dass der Benutzer die nötigen Rechte auf dem Zielserver hat. Bei der Installation der Express-Edition auf einem Remote-Server musst du übrigens darauf achten, dass du am Ende im Configuration Manager TCP/IP als Prodokoll aktivierst und ggf. die Firewall für SQL Server konfigurierst, sonst kommst du nicht drauf.

Grüße
Flo

19.08.2011 - 16:52 Uhr

Hallo Dirk

Wenn beide Datenbanken auf der gleichen SQL Server Instanz laufen, kannst du einfach von DB2 aus auf die User Defined Function (UDF) in DB1 zugreifen indem du die UDF mit dem Datenbanknamen qualifizierst:


USE DB2
GO
SELECT * FROM DB1.dbo.UDF(int1, string1, string2);

Grüße
Flo

18.08.2011 - 20:52 Uhr

Ist es nicht so dass MS Sql Express nur eine aktive Verbindung zulässt?

Nein, du verwechselst die Express Edition mit der Compact Edition.

Grüße
Flo

17.08.2011 - 09:07 Uhr

Umm...? Das mit den ".cs" Files hatte ich überlesen, die sollten natürlich nicht rumkopiert werden.

Meine Aussage beschränkt sich auf config-Dateien und ähnliches.

@FZelle: Hi! Und danke für den Hinweis.

17.08.2011 - 08:38 Uhr

Ja, du benötigst etwas in nativen. NET, am besten mit Source Code- falls du die Securityeinstellungen anpassen musst. Auf jeden fall aber. NET

17.08.2011 - 08:31 Uhr

...(Also ohne CLR)...

naja, CLR bleibt's, auch ohne SQL Server 😉

Ich habe mir jetzt mal den Link angeschaut. Sag mal, kann es sein, dass PDFBox eine Java Lib ist? Dann wird das sicher nicht funktionieren. SQL CLR fährt, aus gutem Grund, ein restriktives Sicherheitskonzept. Ich kann mir nicht vorstellen, dass das die Verwendung Java zulässt.

Grüße
Flo

16.08.2011 - 14:40 Uhr

Hi

Freut mich, dass wir helfen konnten. 😃

Koenntest du mir bitte nur noch sagen, ob ich die Klassen alle mit dem Property "Copy always" versehen muss? (siehe obigen Post)

Das kommt immer darauf an was man wo und wann haben will. Nach deinen Infos würde ich jetzt mal sagen, dass ich's auf "Copy if Newer" stellen würde. Aber du musst dir übelegen wie du es bei dir benötigst, welche Dateien kopiert werden sollen und welche nicht.

Grüße
Flo

16.08.2011 - 13:54 Uhr

Hi

Wenn du XmlDocument.Save() aufrufst und keine Exception ist die Datei definitiv geschrieben worden. Bitte schau dir mal im Explorer das Änderungsdatum der Datei an und prüfe die Datei mit einem Texteditor.

Du musst irgendwo ein Caching Problem haben oder dein Dialog bekommt nicht die neu geladene Konfiguration.

Grüße
Fol