Laden...

Linq2Sql: Multiuser und mehre DataContexte

Erstellt von binaryblob vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.909 Views
B
binaryblob Themenstarter:in
36 Beiträge seit 2008
vor 12 Jahren
Linq2Sql: Multiuser und mehre DataContexte

Hallo zusammen

Habe eine Art Kalender Programm (wie Outlook) in das mehrere Benutzer gleichzeitig Daten schreiben und lesen können.

Benutzt als DB, SQL-Server über Netzwerk mit LINQ.

Ich benutze momentan 1 DataContext in meiner Anwendung, der also einmal erstellt wird und dann alles über denn gemacht wird. Bis das Programm wieder geschlossen wird.

Dazu mehrere Fragen:

  1. Ist das gut 1 DataContext, oder sollte ich für jede Aktione einen neuen instanzieren?

Habe relativ viele solche Funktionen

        internal static void Check(Season season)
        {

            foreach (Season ses in DatabaseContext.Season)
            {
                if (ses == season)
                {
                    SetText("FOUND");
                }
            }
         }

Wenn jetzt aber das übergebene Season nicht vom gleiche DataContext ist, wird es nicht gefunden oder ich müsste noch Attach machen... Irgendwie beschissen! Oder müsste ich direkt den Primarykey checken und nicht die Objekte vergleichen? Irgendwie sehe ich das noch nicht ganz...

  1. Wenn Änderungen von einem anderen User gemacht wurde, müssen das natürlich die anderen Programme mitkreigen, wie kann ich am einfachsten DataContexte Refreshen?

Danke für die Auskunft!

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo binaryblob,

ein DataContext sollte solange leben wie eine "Arbeitseinheit" dauert (engl: Unit of Work). Dadurch ist auch (mehr oder weniger) sichergestellt dass die Daten im Datacontext nicht schal werden.

Für die restliche Anwendugn würde ich auch nicht mit den vom Designer generierten Klassen arbeiten, sondern mit eigenen POCOs. Dann fällt hier die Attach-Problematik so weg, allerdings müssen die Eigenschaften umkopiert werden.

Linq2Sql unterstützt aber auch POCOs. Suche mal danach wenn dir dieser Weg genehm vorkommt. Kurz: mit SQLMetal.exe können diese generiert werden, oder selbst das Xml-Mapping erstellt werden.

Ist das gut 1 DataContext, oder sollte ich für jede Aktione einen neuen instanzieren?

Wie oben erwähnt für jede Arbeitseinheit. Das muss nicht zwangsläufig eine einzelne Aktion sein. ZB Lesen, Ändern und zurückschcreiben ist eine Arbeitseinheit.

Das 2. erschlägst du damit auch.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
binaryblob Themenstarter:in
36 Beiträge seit 2008
vor 12 Jahren

Hallo Gü

Ok, verstehe noch nicht ganz was du mit POCOs meinst, kann du mir da kurz ein vertändliches Bsp. geben?

Danke!

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo binaryblob,

wenn du mit dem Linq2Sql-Designer eine Tabelle von der Datenbank reinziehst ertellt dieser ein Klasse, zB


[TableMapping(....)]
public partial class Kunde : xxx
{
    // haufen Code
}

in der alles mögliche mitgespeichert wird das Linq2Sql zum funktionieren braucht. Damit sind diese Klasse voll abhängig von Linq2Sql (-> persistance aware) und das ist oft nicht praktisch. Dazu gleich mehr.

Wenn die Klasse aber ein POCO ist, also


public class Kunde // : IDataErrorInfo, INotifyPropertyChanged zB
{

}

dann ist diese Klasse unabhängig von einer Speichertechnologie wie Linq2Sql (-> persintance ignorant). Diese Klasse kann somit in jeder Anwendung verwendet werden, serialisiert werden (und somit zB per WCF übertragen), etc. Sie ist auch lösgelöst von einem DataContext und unterstützt somit viel mehr eine mehrschichtige Architektur wie erstere. Diese Klassen verwendest du dann auch in den UI-Schichten der Anwendung.

Schau dir mal das Beispiel in [erledigt] Entity Framework Abfrage mit Beziehungen an. Das gilt für Linq2Sql genauso wie für das Ado.net EF für das ich es erstellt habe.

Beim Speichern/Aktualisieren von DB-Einträgen gehtst du den selben Weg. Das Problem mit dem Attachen ist nicht mehr vorhanden. Auch kann zB ein IEnumerable<T> außerhalb des DataContext zugegriffen werden ohne dass der Fehler "auf das Objekt kann nicht ...." kommt.

Being Ignorant with LINQ to SQL ist ein etwas längerer Artikel der das ausführlicher beschreibt.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
binaryblob Themenstarter:in
36 Beiträge seit 2008
vor 12 Jahren

Hallo Gü,

Danke für die Antwort!

Ich generiere meine DB direkt auf VS mit CreateDatabase().

Jetzt wenn ich das richtig verstehe, müsste ich für jede Entität sozusagen eine zusätzliche Klasse machen.

Aber was ich nicht sehe, schlussendlich will ich ja nicht z.B. auf WCF umstellen, sonder weitherhin die Daten über InsertOnSubmit() in die DB füllen.

Aber da bin ich doch schlussendlich wieder gleichweit, wie am Anfang oder kapiere ich den Ansatz nicht??

Weiter ist das Problem, es geht hier um eine DB mit etwa 20 Tabellen, also etwas ein grober Aufwand, für ein Problem, das doch eigentlich einfacher lösbar sein sollte?!!

Danke

A
350 Beiträge seit 2010
vor 12 Jahren

Hi,

ja sicher kannst du das ganze einfacher lösen, ich denke aber es soll sich ein gewisser Lerneffekt einstellen :
Saubere Trennung von Schichten und ein gewisses Maß an sauberem Code.

Ich denke, wenn du dich an gfoidl Tipps hälst, kannst du sauberen Code produzieren.

Grüße

B
binaryblob Themenstarter:in
36 Beiträge seit 2008
vor 12 Jahren

Ja, allerdings hat man ja mit den Linq Klassen schon eine gute Trennung, darum finde ich das ganze etwas umständlich noch mal zu machen...

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo binaryblob,

es ist so wie Ahrimaan geschrieben hat. Von WCF, udgl. war die Rede.

mit den Linq Klassen schon eine gute Trennung

Eben nicht. Wenn du eine Instanz dieser Klasse in der UI anzeigst dann ist das ganze Linq2Sql-Zeugs auch dabei, da eben diese Klasse von den ganzen Linq-Basisklassen erben und mit Attribute überseht sind. Zum anderen wenn die Instanz vom DataContext getrennt ist dann gibt es Probleme. Daher wird oft - und fälschlicherweise - der DataContext für immer offen gehalten und somit tritt genau eines der Probleme auf die du eingangs beschrieben hast.

Jetzt wenn ich das richtig verstehe, müsste ich für jede Entität sozusagen eine zusätzliche Klasse machen.

Nein.

es geht hier um eine DB mit etwa 20 Tabellen, also etwas ein grober Aufwand,

Ich gehen davon aus dass diese Tabellen nicht 1:1 so in der UI angezeigt werden sollen, sondern entsprechend aufbereitet und spezialisiert. Da dieser Schritt sowieso notwendig ist sind nur diese "spezialisierten" Klassen zu erstellen. ZB wenn in der DB eine Tabelle Produkt und eine Tabelle Hersteller normalisiert ist dann hat Produkt einen Fremdschlüssel zum Hersteller. In der UI wird aber wahrscheinlich nur eine "Kombination" aus beiden Tabellen angezeit, so dass die zu erstellende Klasse etwas wie folgt aussehen kann


public class Produkt : IDataErrrorInfo
{
    public int ProduktId {get; set;}
    public string Name {get; set;}
    public string Hersteller {get; set;}
}

und im Repository entsprechend


public class ProduktRepository : IProduktRepository, IDisposable
{
    private readonly DataContext _db;

    public IList<Produkt> HoleAlleProdukte()
    {
        return _db.Produkte    // die aus dem Mapping von Linq2Sql
            .Select(p => new Produkt{ProduktId = p.Id, Name = p.ProduktName, Hersteller = p.Herteller.Name}
            .ToList();
    }

    public IList<Produkt> HoleAlleProdukte(int herstellerId)
    {
        returns _db.Produkte
            .Where(p => p.Hersteller.Id == herstellerId)
            .Select(p => // wie oben)
            .ToList();
    }

    // usw.
}

darum finde ich das ganze etwas umständlich noch mal zu machen..

Umständlicher ist relativ. Wenn dafür keine Problem auftreten ist es weniger umständlicher als irgendwelche Kunstegriffe die es anderswertig die Probleme zu beheben versuchen 😉

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

B
binaryblob Themenstarter:in
36 Beiträge seit 2008
vor 12 Jahren

Ok, werde das mal anschauen!

Danke euch für die Hilfe!

Gruss blöb