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

20.11.2018 - 14:44 Uhr

Kompilieren kann ich auch alles. Auch die Konsolen-Anwendung kann ich erfolgreich ausfhren. Kannst du den Unit Test ausführen? Hier bekomme ich den genannten Laufzeitfehler.

20.11.2018 - 12:03 Uhr

Hallo

Ist Geschmackssache mit deinem verschachteltem string-Array, aber du kannst z.B. über Linq recht einfach gruppieren und dann Aggretsfunktionen anwenden.

        [TestMethod]
        public void MyTestMethod()
        {
            var arr = new string[][]
            {
                new string[] { "16.11.2018 12:18:46", "1", "1", "1", "1", "1" },
                new string[] { "16.11.2018 12:18:46", "1", "1", "1", "1", "1" },
                new string[] { "17.11.2018 12:18:46", "1", "1", "1", "1", "1" }
            };

            var result = arr.GroupBy(row => row[0])
                            .Select(g => new
                            {
                                Key = g.Key,
                                C1 = g.Sum(row => int.Parse(row[1])),
                                C2 = g.Sum(row => int.Parse(row[2])),
                                C3 = g.Sum(row => int.Parse(row[3])),
                                C4 = g.Sum(row => int.Parse(row[4])),
                                C5 = g.Sum(row => int.Parse(row[5])),
                            }).ToArray();

        }

Viele Grüße
Flo

20.11.2018 - 11:23 Uhr

Freilich. Ist angehängt.

20.11.2018 - 10:30 Uhr

Hallo Zusammen

Danke für eure Hilfe! Scheinbar hast das Verhalten speziell mit Unit Test (.NET Framework) Projekten zu tun.

Ich habe mittlerweile eine Test-Solution erstellen können in der das Verhalten dediziert nachvollziehbar ist.

.NET Standard DLL

using System.Net.Http;

namespace ClassLibrary1.STD {
    public class Class1Std {
        public Class1Std(HttpClient client) {
        }
    }
}

.NET Framework DLL (mit Referenz auf die Standard DLL)

using ClassLibrary1.STD;
using System.Net.Http;

namespace ClassLibrary1.Fx {
    public class Class1Fx : Class1Std {
        public Class1Fx(HttpClient client)
            : base(client) {
        }
    }
}

--> System.Net.Http ausgewechselt über NuGet

Unit Test Projekt (.NET Framework)

    [TestClass]
    public class UnitTest1 {
        [TestMethod]
        public void TestMethod1() {
            var c1 = CreateClass();
        }

        private Class1Fx CreateClass() {
            HttpClient client = new HttpClient();
            Class1Fx c1 = new Class1Fx(client);
            return c1;
        }
    }

--> Führt zu dem genannten Laufzeitfehlet

Console App (.NET Framework)

    class Program {
        static void Main(string[] args) {
            var c1 = CreateClass();
        }

        private static Class1Fx CreateClass() {
            HttpClient client = new HttpClient();
            Class1Fx c1 = new Class1Fx(client);
            return c1;
        }
    }

--> Funktioniert

Viele Grüße
Flo

16.11.2018 - 11:20 Uhr

Hallo

Ich bin sicher nicht der erste mit dem Problem, aber mit der Suche habe ich nichts gefunden.

Problem:
Wir haben eine SOA Architektur, basierend auf ASP.NET Web API (.NET Framework).

Nun startet parallel ein zweites Projekt, welches unsere Basis-Funktionalität verwenden möchte. Dieses Projekt startet mit .NET Core. Da wir nicht 'mal schnell' auf Core gehen können und die anderen natürlich nicht mehr mit .NET Framework starten wollen, habe ich unsere Basis-Funktionalität in .NET Standard überführt. Das funktioniert auch soweit.

Allerdings, habe ich nun das Problem, dass auf die STD Library aufsetzende .NET Framework Libraries Probleme mit der Typ-Kompatibiltät bekommen.

Konkreter Fall:

In der .NET Standard Library gibt es eine Klass mit folgendem Construktor:


    public sealed class RestConfigurationSource : BaseConfigurationSource
    {
//...
//HttpClient is from:
// Assembly netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll
        internal RestConfigurationSource(HttpClient httpClient)
        {
//...

In einem darauf aufsetzendem Unit-Test Projekt (.NET Framework) versuche ich die Klasse zu initialisieren:


        internal static RestConfigurationSource CreateSource()
        {
            FakeHttpMessageHandler fakeResponseHandler = CreateFakeResponseHandler();
//HttpClient is from:
//System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
//C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Net.Http.dll
            var client = new HttpClient(fakeResponseHandler);
//...
            var configSrc = new RestConfigurationSource(client);

Beim Versuch in die Methode zu springen bekomme ich folgende Exception:

Fehlermeldung:
System.MissingMethodException
HResult=0x80131513
Message=Method not found: 'Void MunichRe.Uwpf.Api.Core.Configuration.Rest.RestConfigurationSource..ctor(System.Net.Http.HttpClient)'.
Source=MunichRe.Uwpf.Api.Core.UnitTests
StackTrace:
...

Ist für mich erstmal nachvollziehbar. Die beiden Versionen von HttpClient entsprechen unterschiedlichen Klassen. Aber das muss ja ein Problem sein dass bei dem Arbeiten mit .NET Standard und .NET Framework bedacht wurde.

Könnt ihr mir vielleicht auf die Sprünge helfen, gerne einfach mit einem RTFM Link.

Danke schon Mal!
Flo

08.10.2011 - 19:39 Uhr

also sieht das Mapping für dich soweit richtig aus?

Keine Ahnung 😁 - Das meinte ich mit "kann ich nicht sagen".

Grüße
Flo

08.10.2011 - 17:17 Uhr

Hi Coffeebean

Ich kann dir zwar nicht genau sagen woran es bei dem NH Mapping liegen könnte, aber schau dir doch im SQL Server Profiler mal an was für ein Statement an den Server geschickt wird, vielleicht hilft dir das auf die Spur.

Viel Glück
Flo

08.10.2011 - 14:17 Uhr

Hallo Handsup18

Du kannst z.B. die SqlBulkCopy Klasse verwenden um die Daten an den Server zu senden.

Ansonsten kannst du dir auch mal die mit SQL Server 2008 eingeführten Table Vaued Parameter anzuschauen.

Grüße
Flo

04.10.2011 - 10:45 Uhr

Hallo seeba

Mit EF würde ich, wie Gü bereits geschrieben hat, mal versuchen ob's mit Contains funktioniert.

Mit native ADO.NET würde ich entweder die CSV-Liste der IDs an eine SP übergeben, serverseitig über eine Split-Methode trennen und in eine Temp-Table schreiben mit der man dann joinen kann; oder direkt mit Table Valued Parameters arbeiten.

Grüße
Flo

29.09.2011 - 18:13 Uhr

Die DB Verbindung kannst du auch ganz ohne eigenen Source-Code prüfen.

Explorer -> Rechte Maustaste -> Neue Textdatei -> Dateiendung auf ".udl" ändern -> Doppelklick.
Dann kannst du im "Provider" Register SQL Server auswählen, im "Verbindung" Register alle Infos eingeben und über den Test Button prüfen. Wenn was nicht passt bekommst du da die entsprechende Fehlermeldung.

(Die Combo-Box mit den Servern funktioniert meistens nicht, da einfach den Namen selbst eintragen.)

Grüße
Flo

29.09.2011 - 10:27 Uhr

Wenn SQLite sich im GAC registriert musst du bei der Referenz in deinem Projekt sicherstellen dass "Copy Local" eingestellt ist.

Grüße
Flo

29.09.2011 - 09:44 Uhr

Hallo tofu

Hast du sichergestellt dass beim SQL Server TCP/IP aktiviert ist? Das ist bei SQL Server Express standardmäßig deaktiviert.

Grüße
Flo

22.09.2011 - 11:25 Uhr

Hallo COOLIO88

Fragen:

  1. Habt ihr VS 2010 oder die Database Professional Version von VS 2008?
  2. Haben alle Kundendatenbanken den gleichen Stand? Oder vielleicht nur zwei/drei unterschiedliche Versionsstände?

Grüße
Flo

20.09.2011 - 13:25 Uhr

Wie schon gesagt, ein ORM würde das für dich übernehmen, wenn du native ADO.NET verwendest musst du's selbst mappen.

20.09.2011 - 11:29 Uhr

Hallo

Schau dir mal O/R-Mapper wie NHibernate an. Ansonsten kannst du aber natürlich auch mit reader.GetString(i)/GetInt32(i)/.... in Properties eines Objektes mappen, statt einen String zusammenzuhängen.

Grüße
Flo

20.09.2011 - 07:55 Uhr

Hi Khalid

Danke für die Aufklärung 😃 ! Wusste ich nicht.

Viele Grüße
Flo

20.09.2011 - 00:26 Uhr

Hi

Datenbankseitig definierte DEFAULT Werte bringen in Verbindung mit O/R-Mappern nichts. Wie Coder007 schon gesagt hat, greifen DEFAULT Werte nur wenn die Spalte gar nicht im INSERT Statement enthalten ist, nicht wenn sie mit dem Wert NULL übergeben wird - und genau das ist das was der ORM macht.

Beispiel..

Gehen wir von folgender Tabelle aus:


CREATE TABLE Foo (
   Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED
   ,Bla INT NOT NULL
   ,Bluf VARCHAR(10) NOT NULL DEFAULT '1,2,3'
);

Ein valides INSERT Statement wäre:


INSERT INTO Foo (Bla) VALUES (1);

Der ORM erzeugt jedoch:


INSERT INTO Foo (Bla, Bluf) VALUES (1, NULL);

BTW:
Dein default Wert '1;2;3;4' richt nach einem Verstoß der ersten Normalisierungsform 😉.

Grüße
Flo

19.09.2011 - 22:04 Uhr

Hi Florian

Das angehängte Bild zeigt was Coder007 meinte.

Grüße
Flo

19.09.2011 - 16:49 Uhr

Hallo Nesso

Natürlich kann man auch in T-SQL auch dynamisches SQL erzeugen:



DECLARE @id INT = OBJECT_ID('INFORMATION_SCHEMA.TABLES');
DECLARE @tableName VARCHAR(250) = 'all_objects'
DECLARE @schemaName VARCHAR(250) = 'sys';


-- avoid sql injection
SELECT
   @tableName = QUOTENAME(@tableName)
   ,@schemaName = QUOTENAME(@schemaName);

-- build dynamic SQL
DECLARE @sql NVARCHAR(MAX);
SELECT @sql = N'SELECT * FROM ' + @schemaName + '.' + @tableName + ' WHERE object_id = @idIn';

EXECUTE sp_executesql @sql, N'@idIn INT', @idIn = @id;

Allerdings ist die Frage immer ob man's wirklich braucht. In den meisten Fällen hat man eher ein Design-Problem oder noch nicht die richtige Lösung gefunden.

In wie vielen Tabellen gibt's die Spalte "ID_CR" denn? Warum musst du in mehreren Tabellen nach einer ID suchen?

Grüße
Flo

19.09.2011 - 13:59 Uhr

Lazy Loading hat nichts mit ORM oder nicht ORM zu tun, es ist nur so das einige das out-of-the-box unterstützen.

Lazy Loading ist ein Pattern, nicht eine Erfindung von O/R-Mappern, und kann natürlich auch mit native ADO.NET realisiert werden. Die Frage die du dir beantworten musst ist "Lazy Loading" oder "Eager Loading". Beide Ansätze haben Vor- und Nachteile und die musst du in deinem Projekt gegeneinander abwiegen.

Grüße
Flo

19.09.2011 - 13:44 Uhr

Hi

Nein, nicht ganz so. Du stellst den EditMode des Grids beispielsweise auf "EditProgrammatically" (wobei ich erstmal schauen würde ob nicht eine der anderen Möglichkeiten eh schon passt). Setzte das Grid nicht auf ReadOnly, sondern nur die Spalten die du nicht editieren willst. Wenn du's dann wirklich mit Doppelklick willst, rufst du im CellDoubleClick die BeginEdit Methode auf.

Grüße
Flo

19.09.2011 - 12:37 Uhr

Hallo #coder#

Die Datenbank steht, mit dem Entity Framework 4.1

Nope, ist alles Konfigurationssache. Nur wenn das Code-First Template verwendest wird davon ausgegangen, dass du noch keine DB hast. Wenn du das Standard-Template, das Change-Tracking Entities Template oder einfach gar keines verwendest kannst du dir das Modell aus einer bestehenden DB erzeugen lassen.

Ein Problem ist, das die Anwendung mit SharePoint 2010 laufen muss

Das verstehe ich jetzt nicht. Meinst du die Anwendung muss auf dem gleichen Server laufen auf dem der SharePoint installiert ist und da darf kein neuer .NET Framework installiert werden? Ansonsten wird es dem SharePoint doch recht egal sein welche .NET Version die Clients haben, oder?

Zum Laden deiner Orders schließe ich mich Gü's Vorschlag an. ORM mit Lazy Loading oder Order-Repository und LoadForCustomer Methode. Das lässt sich recht gut mit der .NET 4.0 Lazy<T> Klasse realisieren.

Grüße
Flo

14.09.2011 - 21:29 Uhr

Hi

Schau dir mal die "EditMode" Eigenschaft des DataGridView an.

Grüße
Flo

14.09.2011 - 21:25 Uhr

Hi Lumbra

Versteh' mich nicht falsch aber ich würde sagen da passt irgendwas anderes nicht.

Führ' das hier mal aus:



      [Test]
      public void SampleUsage() {
         string[] extensions = new[] { ".zip", ".7z", ".rar", "blubber", "blubb" };

         foreach (var test in extensions) {
            switch (test) {
               case ".7z":
               case ".zip":
               case ".rar": 
               case ".gzip":
                  break;
               default:
                  Debug.WriteLine(test);
                  break;
            }
         }
      }

Grüße
Flo

14.09.2011 - 20:19 Uhr

Hi moson

Ich bin mir nicht sicher ob ein Trigger hier die richtige Wahl ist. Wenn ich Yheeky richtig verstanden habe, geht es darum neue Zeilen jetzt einzufügen und später zu verarbeiten, der Trigger feuert sofort.

Man könnte, wenn man will, den Trigger verwenden um die Schedules im SQL Server Agent zu erzeugen. [subjektiv]Allerdings bin ich kein großer Freund von viel Logik in Triggern[/subjektiv]

Grüße
Flo

14.09.2011 - 15:59 Uhr

@Diräkt: Jepp, ich find's auch in TSQL immer wieder sehr praktisch. Irgendwann hat es mir in C# einfach gereicht 😛

14.09.2011 - 13:56 Uhr

Mache ich mit:


    public static class StringExtensions
    {
        public static string Left(this string s, int length)
        {
            length = Math.Min(s.Length, length);
            return s.Substring(0, length);
        }

        public static string Right(this string s, int length)
        {
            length = Math.Min(s.Length, length);
            return s.Substring(s.Length - length, length);
        }
    }

Grüße
Flo

14.09.2011 - 09:18 Uhr

Hi Motzi

Ich schließe mich Gü an. Ein Projekt sehe ich eben falls nicht als Angebot. Ich sehe die Relation sogar fast als n:m Beziehung. Theoretisch können ja mehrere Angebote zu einem Projekt erstellt werden und aus einem Angebot können ggf. mehrere Teil-Projekte werden (das kommt aber auf die Firmenpolitik an).

Grüße
Flo

14.09.2011 - 09:16 Uhr

Hi Coffeebean

Ich weiß nicht wo da die Grenzen liegen, ich habe aber schon in Umgebungen gearbeitet wo täglich einige tausend neue Schedules erzeugt wurden und auch schon mit Agent Jobs die im Minutentakt gelaufen sind. Wenn's aber mehrere tausend Jobs pro Minute würden habe ich bislang immer andere Wege gewählt.

Wenn ich mich recht erinnere muss man, wenn man immer wieder neue Schedules erstellt, also nicht einen der einfach immer wieder läuft, halt die alten Schedules regelmäßig löschen. Sonst läuft einem die msdb voll.

Grüße
Flo

14.09.2011 - 08:20 Uhr

Guten Morgen

Bei. 30 Einträgen gar kein Problem. Erzeuge einfach bei jeden Eintrag einen Schedule für einen SQL Server Agent Job.

Grüße
Flo

13.09.2011 - 12:11 Uhr

Das ganze befindet sich in einer Basis-Klasse...


public void Initialize(params object[] environmentParameters)
{
   // get the environment, is the first dictionary
   foreach (Dictionary<string, string> item in environmentParameters)
   {
       m_Environment = item;
   }
}

12.09.2011 - 20:16 Uhr

Hallo Flok

Richtig, das auf Stackoverflow genannte Argument "Wenn man auf einen anderen ORM wechseln will" sehe ich auch eher esoterisch. Allerdings sehe ich, neben den bereits genannten, andere Gründe.*DB Refaktorierung. Was wenn die DB, sei es aus Performance-Gründen oder irgendwelchen anderen, mal teilweise restrukturiert werden muss? Wenn du die LINQ2EF Queries überall im Code verwendest wirst du evtl. große Teile des Systems anpassen müssen. *Duplizierter Code. Gleiches Problem wie im vorherigen Grund, aber andere Sichtweise. Es gibt normalerweise eine endliche Anzahl an Abfragen die man aber z.T. an sehr vielen Stellen benötigt. Jedesmal 3-8 zeilige LINQ-Queries zu kopieren ist schlicht ein Bruch der Kapselung und Zuständigkeiten. *Mehrere Datenquellen. Immer mehr Firmen stellen fest, dass sie die gleichen Daten (Kunden, Mitarbeiter, Produkte, ...) in sehr vielen Systemen parallel pflegen oder synchronisieren müssen. Was wenn du eine zweite Datenbank für Kundeninformationen und beispielsweise einen Web-Service für Mitarbeiterinformationen ansprechen musst? O/R-Mapper können meist nur mit einer DB und fast nie mit anderen Datenquellen arbeiten. Dann fängt man an N unterschiedliche Datenquellen zu verwalten und versucht die in den oberen Layern gegeneinander valide zu halten. *Skalierung. In den meisten Systemen sind ca. 80% aller DB Aktionen lesend und nur 20% schreibend. Du kannst Datenbanken spiegeln/replizieren und lesende Aktionen auf beliebig viele Server verteilen und nur noch schreibende Aktionen auf den Master-Server schicken. Bringt 5-mal mehr Leistungsfähigkeit, geht aber nur wenn man intern den EF auf unterschiedliche DBs switchen kann. *Versionierte Daten. Stammdaten physikalisch zu löschen geht in den wenigsten Systemen. Nur weil ein Artikel 'gelöscht' wird will keiner alle daran hängenden Aufträge auch löschen, also bekommt der Artikel ein "gelöscht" Flag. Das darf man ab sofort durchs ganze System mitschleifen. Gleiches gilt für Stammdaten die geklont werden wenn sie sich ändern und immer nur die letzte Version aktuell gültig ist. *Ein spezielles Schmakerl des EF. Das Ergebnis einer LINQ2EF Query ist ein ObjectQuery Objekt. Dies enspricht nicht einer Liste an Ergebnissen, sondern eher dem SQL Statement welches deine LINQ Abfrage definiert. Wenn du dieses IEnumerable mehrfach durchläufst feuerst du jedesmal eine neue Abfrage an den Datenbankserver. Das ist zum einen unnötige Belastung, kann aber vor allem immer wieder zu unterschiedlichen Ergebnissen führen. Der simple Aufruf von ToList() behebt das Problem, muss aber abermals an allen Stellen beachten werden wo man LINQ2EF verwendet und das ist leichter wenn es weniger Stellen sind.

Ich könnte jetzt nach Belieben weitere Argumente aufführen 😉. Letzten Endes liegt es von dir und deinem Projekt ob du einfach den EF in den oberen Layern verwendest oder ihn doch besser wegkapselst, aber es gibt schon ein paar (echte) Gründe die, meiner Meinung nach, für eine Kapselung sprechen.

Grüße
Flo

12.09.2011 - 15:34 Uhr

Hallo Coffeebean

Das ist ein riesiges Thema und nennt sich Datenbank Monitoring.

Hier gibt's nicht den richtigen Weg. Es kommt erstmal darauf an wie wichtig die Verfügbarkeit ist (z..B. wie viel Geld kostet ein Ausfall von wie viel Zeit?).

Dein Test (Open()) ist ein sehr rudimentärer Ansatz. Je nach Brisanz kannst du Wait-Locks prüfen, IO-Locks, Server-Traces, Aktive Verbindungen, Index-Zustände, ........

Für sowas gibt's viele Tools (die nicht ganz billig sind), aber auch tausende Artikel im Internet.

Grüße
Flo

Edit: Satzstellung korrigiert.

11.09.2011 - 22:30 Uhr

Hallo Flok

Wenn's dir nur um Änderungen zwischen deinen Views innerhalb deiner Anwendung geht kannst du deinem Data Layer einen statischen Event geben an dem sich die Instancen deines Data-Contexts registrieren (und wieder austragen 😉 ). Du kannst's dir einfach machen und einfach einen "DataChanged" Event werfen oder die Sache granularer aufziehen, woebei du einen Event pro Entity Typ wirfst.

Wenn's um globale Änderungen, auch von anderen Arbeitsplätzen, geht kannst du den SQL Server Service Broker und Event Notifications verwenden. Hier aber auf die Menge der registrieten Clients achten. Wenn du viele Clients hast solltest du das über einen Middle-Tier abbilden.

Grüße
Flo

10.09.2011 - 12:55 Uhr

Hallo

Möglichkeit 1:
(Jetzt war FZelle schneller mit dem ersten Teil meiner Antwort..)

Möglichkeit 2:
Verwende in deiner Y Datenbank einen zusammengesetzten PK aus der X1..XN ID und einer zusätzlichen Spalte welche den Standort qualifiziert, das ist recht easy. Ich würde keine ID-Ranges verwenden. Erstens weiß man nie was noch an Daten kommt und zweitens würde das voraussetzen dass deine bestehenden Daten in allen Standorten angepasst werden müssen um erstmal in ihren Range zu kommen.

beim Import extrem viele geschachtelte Schleifen

Dann ist dein Import falsch konzipiert.

Grüße
Flo

10.09.2011 - 12:42 Uhr

Hallo Kostas

Ich meinte nicht Lazy Loading, ich meinte die .NET Lazy<T> Klasse - oder irgendwas ähnliches. Lazy Loading bezieht sich normalerweise auf das automatische Nachladen von Referenzierten Objekten. Gerade in Projekten mit hohem DB Traffic ist Lazy Loading mit Vorsicht zu genießen. Ich meinte eher eine Möglichkeit dedizierte Felder, wie BLOBs, nur bei Bedarf zu laden, auf Feld, nicht Objekt-Ebene. Hier gilt zwar die gleiche Vorsicht wie bei Objekt Lazy Loading, allerdings würde das die Design-Freiheiten auf beiden Seiten erhöhen. Aber egal...

.. mögen meine Fragen für Euch sich anhören wie aus einem anderen Stern. Dafür bitte ich um Vergebung.

Du brauchst nicht um Vergebung bitten, du hast meines Wissens nach nichts angestellt, oder? 😉

Ich verwende zwar O/R-Mapper, aber empfehle immer den Mapper außerhalb deines DAL versteckt zu halten. Falls irgendwann mal eine Anforderung kommt die der ORM nicht oder nur schwer abbilden kann bleibt man trotzdem in der Lage einzugreifen, ohne gleich die komplette Anwendung umwerfen zu müssen. Ich verwende einen eigenen Data-Container der den ORM kapselt und anhand von Repositories die Daten bereitstellt.

Grüße
Flo

09.09.2011 - 19:11 Uhr

Hallo Kostas

Zur Tabellenstruktur:
Der JOIN hat natürlich seinen Preis, allerdings solltest du - wie FZelle schon gesagt hat - deine Tabellen immer aufteilen, wenn du Haupt- und Zusatz-Informationen hast. SQL Server arbeitet mit 8k großen Daten-Pages und je mehr Zeilen in eine Page passen, desto schneller der Zugriff. Die Auslagerung deiner Adressen ist genau der richtige Ansatz.

Die Bilder deiner Artikel würde SQL Server zwar sowieso ausgelagern wenn die Daten-Zeilen größer als 8k wird, allerdings gehe ich davon aus das der ORM die Bilder immer laden würde wenn du die Artikel lädst und das macht ja keinen Sinn. ((Muss gestehen, dass ich nicht weiß welche Möglichkeiten man mit dem ORM vom Telerik für Möglichkeiten hat. Vielleicht unterstützt der die Verwendung der .NET Lazy<T> Klasse - was super wäre.)

Zu deinem Problem der Polymorphie:
Du könntest deine Domain Objekte so designen, dass diese nicht selbst die Daten beinhalten, sondern eine Referenz auf ein Daten-Objekt aus dem ORM. Damit werden die ORM Objekte zwar zu DTOs degradiert, allerdings hast du so alle Freiheit wie du deine Domain Objekte designst und welche Funktionalität du wo unterbringst.

Grüße
Flo

08.09.2011 - 19:09 Uhr

Hallo Diräkt

Wie wäre es mit Serilisierung? Sicherstellen, dass Lazy-Loading aus ist, den Graphen serialisieren und wieder in eine neue Referenz laden. Dann musst du zwar immernoch die PKs anpassen, aber du hast dir schon ein ganzes Stück Arbeit gespart.

Grüße
Flo

05.09.2011 - 15:36 Uhr

Hallo caprifisher

Wenn's dir darum geht die Daten mit einem Statement in beide Tabellen zu schreiben kannst du die OUTPUT Klausel verwenden:


DECLARE @A TABLE (Foo INT, Bar VARCHAR(10), Blubber DATETIME2);
DECLARE @B TABLE (Foo INT, Bar VARCHAR(10));


INSERT INTO @A
OUTPUT
   inserted.Foo
   ,inserted.Bar
INTO @B
VALUES (1, 'a', SYSDATETIME());

SELECT * FROM @A;
SELECT * FROM @B;

Grüße
Flo

05.09.2011 - 10:57 Uhr

Hallo Nesso

Der korrekte Weg um über SQLCLR auf die aktuelle Datenbank zuzugreifen ist "Context Connection" über den Connection-String anzugeben.


SqlConnection cn = new SqlConnection("Context Connection=true");

Ansonsten würde ich dir empfehlen dir mal folgenden Artikel durchzulesen:
[Artikelserie] SQL: Parameter von Befehlen

Grüße
Flo

01.09.2011 - 12:06 Uhr

Hi tkrasinger

Wenn du mit SQL Server Enterprise Edition arbeitest kannst du SQL Server TDE (Transparent Data Encryption) arbeiten.

Hier ein paar Links dazu:
Transparent Database Encryption in SQL Server: A Planning Guide
TDE Setup and Administration Scripts
Understanding Transparent Data Encryption

Grüße
Flo

Edit: Habe noch einen MS Link dazu gepackt.

01.09.2011 - 09:54 Uhr

Hi

Für alle die es evtl. noch nicht mitbekommen haben, Microsoft lässt OLEDB sterben, dafür wird jetzt ganz neu auf neue ODBC Treiber gesetzt. Unter anderem auch wegen SQL Server Azure.

Quelle hierzu:
Microsoft is Aligning with ODBC for Native Relational Data Access

Grüße
Flo

30.08.2011 - 20:51 Uhr

Hi

Gerade wenn du eigene DTOs dazwischen schiebst hast du eine gute Grundlage für Zukunftssicherheit. Deine Objekte bleiben damit von Änderungen in den Schnittstellen recht unberührt, du musst nur ggf. die Mapping-Schicht, welche in deinem Fall den DAL darstellt, anpassen.

XML als Zwischenformat zu verwenden sehe ich als einen sehr guten Ansatz. (Mache ich selbst immer so wenn ich kann.)

Grüße
Flo

30.08.2011 - 20:46 Uhr

Hi

Hast du zu diesem Thema eventuell ein gutes Beispiel / Tutorial, wo man das einmal nachlesen kann?

Yup, zum Thema Datenaustausch zwischen dem Data Access Layer und dem Business Logic Layer habe ich selbst mal einen Blog geschrieben (englisch): Layers, Boundaries and how to Exchange Data. Allerdings konzentriert sich der auf diese beiden Layer und setzt voraus dass man sich mit der Three-Layer soweit auskennt.

Hier ein Link aus dem Forum in dem das Thema auch diskutiert wurde:
Schichtenmodell Verständnisfrage bez. C# Implementierung

Gerade wenn man's als Hobby macht würde ich aber empfehlen einen O/R-Mapper wie Entity Framework zu verwenden, der nimmt einem viel Arbeit ab. Hierzu gibt's viele gute Artikel im Internet, z.B. hier Walkthrough: POCO Template for the Entity Framework

Sobald du deine Anwendung in ihre Aufgaben aufgeteilt hast wirst du sehen, dass viele Probleme wesentlich leichter zu bewerkstelligen werden. Wenn deine Form z.B. einen DatenContext hält können sich den alle User-Controlls teilen (Achtung, wenn du mit Threads arbeitest musst du die synchronisieren).

Wenn du, wie in einigen der Links oben beschrieben mit Repositories arbeitest werden sich viele DB Abfragen automatisch erledigen, weil du einfach cachen kannst.

Glaube jetzt hast du erstmal was zum lesen 😛

Grüße
Flo

30.08.2011 - 19:40 Uhr

Hi

Technisch:
Bei SQL Server kann man im Connection-String angeben ob die Connection gepooled werden soll oder nicht, bzw. über statische Methoden den Pool leeren.

Konzeptionell:
Ein User-Controll sollte nie eine Verbindung auf eine Datenbank herstellen. Dafür gibt es einen anderen Layer in einer Anwendung.

Wenn du die Datenzugriffe an eine zentrale Stelle bekommst kannst du auch die Zugriffe besser koordinieren.

Möglichkeit 1 ist Caching:
Wenn immer wieder die gleichen Daten benötigt werden müssen die nicht immer wieder neu von allen Komponenten aus der Datenbank genuckelt werden.

Möglichkeit 2 Synchronisieren:
Synchronisiere deine Zugriffe so dass immer nur 1-2 Verbindungen gleichzeitig geöffnet werden, dann kann der Connection-Pool auch seinen Job tun.

Grüße
Flo

30.08.2011 - 19:34 Uhr

Hi ProgrammierTroll

Es kommt darauf an was die Anforderungen an deine Anwendung sind.

Wenn's einfach nur darum geht alle XML Files zu verarbeiten und fertig würde ich einen sehr rudimentären "Mapper" verwenden der einfach File für File deserialisiert (z.B. mit dem XmlSerializer) und als Objekte zurückliefert. Hier stellt sich dann nur noch die Frage ob das von der XSD.exe erzeugte Objekt-Modell so aussieht wie es in deiner Business-Schicht Sinn macht, sonst müsstest du eine Transformation (in C# oder XSLT) dazwischenklemmen.

Wenn es eher um einen mächtigeren Store in Form von XML Files geht wird's spannend. Solange man alle 'Abfragen' aus den Dateinamen ableiten kann ist es noch recht easy, wenn du aber auf Referenzierende Dokumente zugreifen musst oder Abfragen auf Daten innerhalb der Files durchführst musst du mal schauen was es gibt (ich kenne das Repository von Golo und Peter nicht, kann die also nicht beurteilen) oder auf Low-Level XPath/XmlReader zurückgreifen.

Grüße
Flo

29.08.2011 - 15:20 Uhr

Naja, als Entwickler muss (/soll 😉) man auch nicht unbedingt Admin-Rechte auf den produktiven Datenbankservern haben, aber du wirst ja einen Test-Datenbankserver haben und da kannst du das testen.

Grüße
Flo

29.08.2011 - 14:11 Uhr

SQL Server Management Studio -> Menü -> Tools -> SQL Server Profiler

Du benötigst auf dem SQL Server sysadmin Rechte, wenn du die auf eurem Entwicklungsdatenbankserver nicht hast lass sie dir geben.

Grüße
Flo

29.08.2011 - 13:54 Uhr

Hallo Neidhard

Schau mal in den SQL Server Profiler ob's da bei der Ausführung irgendwelche Unterschiede gibt.

Grüße
Flo

29.08.2011 - 13:52 Uhr

Hi

@m.grauber
Freut mich dass wir helfen konnten. 😃

@tkrasinger

Flo's Lösung ist also zu 99% richtig

Touchet für meine stümperhafte LEFT JOIN Lösung, der NOT EXISTS passt so aber schon ;-P

Zu deinem verschachteltem LEFT JOIN, sehr schick! Den Ansatz habe ich so noch nicht gesehen. Werde mir die Performance auf jeden Fall bei Gelegenheit mal genauer anschauen.

Grüße
Flo