Laden...

[erledigt] EntityFramework + DBContext: Connection öffnen

Erstellt von m.grauber vor 10 Jahren Letzter Beitrag vor 10 Jahren 5.891 Views
M
m.grauber Themenstarter:in
343 Beiträge seit 2010
vor 10 Jahren
[erledigt] EntityFramework + DBContext: Connection öffnen

Hallo!

Folgendes hat vor der Umstellung von Object-Context auf DB-Context einwandfrei geklappt:


MyEntityConnection = new EntityConnection(entityBuilder.ToString());
//... einige Schritte...
MyEntities myEntities = new MyEntities(MyEntityConnection);

Leider kann dem Konstruktor in der untersten Zeile nun keine EntityConnection übergeben werden, da nun der DB-Context das nicht mehr unterstützt. 🙄

Wie kann ich es ändern? (Da es hier sehr viel Beiwerk im Programmcode gibt, sollte "MyEntityConnection" unbedingt erhalten bleiben und weiterhin übergeben werden.)


MyEntityConnection = new EntityConnection();
//... einige Schritte...

// Nun ohne Parameter - funktioniert:
MyEntities myEntities = new MyEntities();

// Diese Zeile läuft natürlich nicht, wie kann ich die EntityConnection dann übergeben? Wie muss diese Zeile lauten:question:
myEntities.Configuration.Entity = MyEntityConnection;

Irgendwie muss ich nun in der letzten Zeile noch MyEntityConnection übergeben. "myEntities.Configuration.Entity" gibts natürlich nicht. Wie wird das dann gemacht?

Vielen Dank!!!!!

Mfg
Michael

PS: Ich stelle nur Fragen, wenn ich in Büchern, im Web und in Foren nichts gefunden habe. Dumme Fragen bitte ich zu entschuldigen!

:] VISUAL STUDIO 2017 + .NET FRAMEWORK 4.5 + SQL-Server 2012 :]

16.807 Beiträge seit 2008
vor 10 Jahren

Mal ehrlich. Wieso schaust Du die ADO.NET Doku nicht an oder denkst nach, was der automatisch generierte Code tut?
Du muss den Generator nicht nutzen!!!

Der Generator erzeugt Dir zwar die Klasse; aber Du kannst sie doch verändern, wie Du lustig bist.
Google zeigt Dir sehr viele Lösungen. Erster Treffer: EF6 DBContext Dynamic Connection String

Beachte [Hinweis] Wie poste ich richtig? 1.1 und zeig doch ein bisschen mehr Eigeninitiative, wenn Du Hilfe verlangst. Bist lang genug dabei....

M
m.grauber Themenstarter:in
343 Beiträge seit 2010
vor 10 Jahren

Hallo Abt!

Erst einmal besten Dank.

Du muss den Generator nicht nutzen!!!

Das heißt, ich soll den Generator nicht nutzen? Ich habe mir inzwischen ernsthaft überlegt, zurück zu gehen zu ObjectContext und dann den Code, den der Generator erstellt für die zukünftigen Tabellen manuell zu schreiben.

  • Das ist wahrscheinlich 1000 mal weniger Aufwand als die Umstellung auf DBContext.
  • Zudem brauche ich nicht immer die Tools vom Team zusätzlich installieren

1.) Nur wie lange kann ich so arbeiten? Wird der ObjectContext oder der direkte Zugriff darauf irgendwann abgeschafft? Oder wird er weiter bestehen? (DbContext ist ja eigentlich nur ein Wrapper darum)

Der Generator erzeugt Dir zwar die Klasse; aber Du kannst sie doch verändern, wie Du lustig bist.

---> Und genau das will ich nicht. Der Code wird ja jedes mal mit dem einfügen einer neuen Tabelle neu generiert. Alle Änderungen müsste ich dann immer erneut ausführen. Und es ist ja an sich nicht empfohlen, diese Dateien zu verändern.

Was auf Deiner Seite beschrieben wird habe ich nun versucht manuell zu machen:


  MyEntityConnection = new EntityConnection(sqlBuilder.ToString());

Das funktioniert derzeit trotzdem nicht, da Fehler "Schlüsselwort wird nicht unterstützt:" "data source".

sqlBuilder.ToString() enthält folgendes:

"Data Source=.;Initial Catalog=MyDB;Integrated Security=True;Pooling=False;MultipleActiveResultSets=True;Connect Timeout=6"

Übergebe ich den String aus Interesse einfach direkt und entferne "Data Source=.", bemängelt er das nächste Schlüsselwort "Initial Catalog".

Warum akzeptiert er nicht einmal mehr einfache Connectionstrings?

Momentan sehe ich leider nur noch rot, da mich diese Umstellung auf DBContext völlig aus der Bahn wirft. Bitte nochmals um Hilfe!!!!

Mfg
Michael

PS: Ich stelle nur Fragen, wenn ich in Büchern, im Web und in Foren nichts gefunden habe. Dumme Fragen bitte ich zu entschuldigen!

:] VISUAL STUDIO 2017 + .NET FRAMEWORK 4.5 + SQL-Server 2012 :]

211 Beiträge seit 2008
vor 10 Jahren

Hi,

was Abt glaub ich meint ist, dass du dich damit beschäftigen sollst wie der "Prozess" aussieht und wie der Generator arbeitet.

Im Grunde besteht das EntityFramework aus der Basisklasse DbContext und die Ableitung davon hat halt, die jeweiligen Properties und POCO Klassen.
Falls du nun gerne einen Konstruktor hast dann musst du die Templatevorlage ändern - also die *.tt Files,
und diese werden bei jedem speichern/ändern vom Modell neu ausgeführt.

Konkret bedeutet es bei dir du musst im DbContext Generator File dir den Konstruktor raussuchen,
diesen erweitern oder überladen und die Basisklasse von DbContext hat bereits den gewohnten Konstruktor für den Connectionstring.
Ist also im Grunde eine Zeile die du ändern musst und damit hast du das Problem erledigt.

Ich hab über T4 mal einen ganzen Vortrag gehalten und die Unterlagen findest du hier:
T4 Code Generation

Kontakt & Blog: www.giesswein-apps.at

M
m.grauber Themenstarter:in
343 Beiträge seit 2010
vor 10 Jahren

Hallo LatinChriz!

Zuersteinmal auch an Dich vielen Dank! 👍

Ich habe mir wirklich Zeit genommen, komme aber noch immer nicht weiter. Du schreibst:

Falls du nun gerne einen Konstruktor hast dann musst du die Templatevorlage ändern - also die *.tt Files,
und diese werden bei jedem speichern/ändern vom Modell neu ausgeführt.

--> Abt sandte den Link, bei dem der Konstruktor überladen werden sollte. Dieser Abschnitt befindet sich bei mir aber in der MyModel.Context.cs - nicht jedoch im tt-File❔


   public partial class MyEntities : DbContext
    {
        public MyEntities()
            : base("name=MyEntities")
        {
        }
        .....

Wenn ich ihn nun wie im Beispiel angegeben erweitere, schreibe ich in der MyModel.Context.cs folgendes dazu:

public MyEntities(string connectionString) : base(connectionString)
{
Database.Connection.ConnectionString = connectionString;
}

Nun lässt sich meine Zeile


MyEntities myEntities = new MyEntities(entityBuilder.ToString());

zwar kompilieren aber löst eine Exception während der Ausführung aus:

Der Eintrag "MyEntities" wurde bereits hinzugefügt.

Übergebe ich sqlBuilder.ToString() geht es auch nicht. Da kommt die Meldung:

Schlüsselwort wird nicht unterstützt: 'data source'.

Theoretisch brauche ich auch die Überladung des Konstruktors im selbst generierten File wie oben angegeben ja gar nicht und könnte direkt folgendes angeben:


MyEntityConnection = new EntityConnection();
   MyEntityConnection.ConnectionString = entityBuilder.ToString();
// oder
   MyEntityConnection.ConnectionString = sqlBuilder.ToString();

Und das bringt mir aber leider natürlich die identischen Fehlermeldungen wie oben. Das Problem ist nicht die Überladung des Konstruktors, sondern das mein Connection-String nicht akzeptiert wird. Das Projekt wurde ja nur von ObjectContext auf DB-Context umgestellt.

Eine Erklärung könnte sein, dass beim DB-Context der Context ja bereits existiert und daher auch die Meldung kommt. Also scheint der entityBuilder.ToString()) zwar die richtige Wahl zu sein, wird jedoch vom T4-Template verhindert?

  • Ist das so?

  • Nur wie kann ich dann die Daten zur Laufzeit übergeben/ändern?

  • Einen ähnlichen Artikel wie Abt habe ich hier gefunden:

http://social.msdn.microsoft.com/Forums/en-US/deab3d98-c392-496a-a6ee-aa181157ebc6/passing-a-connectionstring-in-dbcontext-constructor?forum=adodotnetentityframework

Ich bin gerade wirklich am Verzweifeln! 🤔 🤔

Vielen Dank für Eure Mühe!!!

Mfg
Michael

PS: Ich stelle nur Fragen, wenn ich in Büchern, im Web und in Foren nichts gefunden habe. Dumme Fragen bitte ich zu entschuldigen!

:] VISUAL STUDIO 2017 + .NET FRAMEWORK 4.5 + SQL-Server 2012 :]

P
1.090 Beiträge seit 2011
vor 10 Jahren

Vergleich mal deinen ConectionString mit den vom EF erzeugten.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

16.807 Beiträge seit 2008
vor 10 Jahren

Ich hab den Eindruck, dass Du Dir das ganze Thema nicht wirklich anschaust.
Du ergoogelst wahrscheinlich hier ein Snippet und fragst da ein bisschen nach. Aber wirklich tief befassen mit der Generierung und den T4 Files hast Du sicher nicht - das unterstell ich Dir jetzt einfach mal.
Denn wenn Du das getan hättest, dann würdest Du gar nicht so viele Fragen haben. Da ich die Eigeninitative einfach weiterhin nicht sehe ist das auch mein letzter Beitrag dazu.

Die TT-Dateien generieren den Abschnitt

 public partial class MyEntities : DbContext
     {
         public MyEntities()
             : base("name=MyEntities")
         {
         }
         ..... 

Wäre das nicht im TT File dann hättest Du den Abschnitt auch nicht. Logisch, nicht?

Und nochmals: die TT-Dateien sind eine Hilfe mit einem Vorschlag seitens MS. Du kannst diese nutzen - musst es aber nicht. Wenn Dir der Inhalt nicht ausreicht oder passt, dann verzichte auf die TT Dateien, oder ändere sie.
Du kannst von MS oder von uns beim besten Willen nicht erwarten, dass Dir die alles fein säuberlich auf dem Präsentierteller servieren. Die TT-Dateien sind eine simple UNTERSTÜTZUNG keine komplette Abnahme. Du bist Entwickler. Du musst auch "etwas" selbst machen.
Und ja: die TT Files decken nicht jeden Fall ab.

Und womögich deckt das TT File einfach auch nicht die "Anforderung" ab, die Du an den Code stellst; deswegen fliegt die Connections.
TT Files sind schön und gut; aber a) muss man wissen, was sie tun und b) muss man wissen, wie der generierte Inhalt anzusprechen ist. Beide ist bei Dir wohl eher nicht der Fall.

Du kannst problemlos den generierten Context links liegen lassen und eine eigene Klasse erstellen, die von DbContext erbt und die nutzen - nach Deinen wünschen. Wo ist das Problem? Keine Lust?

Beschäftige Dich endlich richtig mit dem EF6. Probiers an einer Testanwendung aus und 90% Deiner Fragen kannst Dir eigentlich selbst beantworten. Wir sind nich Deine Lehrer.
Sorry wenns so deutlich ist.

M
m.grauber Themenstarter:in
343 Beiträge seit 2010
vor 10 Jahren

Hallo Palin und Abt!

Vergleich mal deinen ConectionString mit den vom EF erzeugten.

Super und erst einmal vielen Dank! 👍 👍 👍 Damit führtest Du mich bereits weiter in Richtung Lösung! Die vom EF erzeugten steht in der app.config. --> Und die Fehlermeldung besagte ja: "Der Eintrag "MyEntities" wurde bereits hinzugefügt."

Das brachte mich auf die Idee, in der app.config den Abschnitt, wo die Verbindungszeichenfolge gespeichert wird auszudokumentieren. Also alles im Bereich "<connectionStrings>". Und siehe da: Das Programm öffnet nun korrekt die Connection! 👍 👍 👍

Folgendes wurde automatisch eingefügt:


protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

Nun läuft das Programm schon einmal los.

Aber schon bei der ersten Abfrage von der Datenbank kommt nun folgender Fehler:

„Code, der mit den T4-Vorlagen für die Database First- und Model First-Entwicklung generiert wurde, funktioniert im Code First-Modus möglicherweise nicht ordnungsgemäß. Wenn Sie weiterhin 'Database First' bzw. 'Model First' verwenden möchten, stellen Sie sicher, dass die Entity Framework-Verbindungszeichenfolge in der config-Datei der ausführenden Anwendung angegeben ist. Um die mit 'Database First' oder 'Model First' generierten Klassen im Code First-Modus zu verwenden, fügen Sie eine ggf. erforderliche Zusatzkonfiguration mithilfe von Attributen oder der DbModelBuilder-API hinzu, und entfernen Sie dann den Code, der diese Ausnahme auslöst.“

>> Klar, weil ich ja vom DB-First her komme.

Ich würde wahrscheinlich auf "Code First with an existing database" gehen

Und dadurch steht erneut eine Grundsatzentscheidung an:

Ist nun "data annotations" oder "fluent api" empfohlen?

Vielen Dank für Eure Hilfe!!!! 👍 👍 👍

Mfg
Michael

PS: Ich stelle nur Fragen, wenn ich in Büchern, im Web und in Foren nichts gefunden habe. Dumme Fragen bitte ich zu entschuldigen!

:] VISUAL STUDIO 2017 + .NET FRAMEWORK 4.5 + SQL-Server 2012 :]

M
m.grauber Themenstarter:in
343 Beiträge seit 2010
vor 10 Jahren

Hallo Abt!

Ich verstehe, das Du keine Lösung vorkauen möchtest und ich selbst darauf kommen muss. Bitte verstehe auch mich: Ich bin seit einer Woche an der Umstellung von ObjectContext auf DBContext und mit dem übernommenen Code wirklich am verzweifeln. Zudem habe ich auch ein Zeitproblem, da ich nicht damit gerechnet habe, dass das Update von EF 5 auf EF 6 so aufwendig ist.

Zuersteinmal zurück zu EF 5 will ich nach der Woche aber leider auch nicht, da ich so extrem viel Arbeit hineingesteckt habe.

Ich bin froh über jede Hilfe, da ich weiß, das ihr das freiwillig macht. Dafür Hut ab! 👍 👍 👍

Ich habe im letzten Eintrag meine Fortschritte geschrieben und hoffe, Du kannst mich nochmals bei der Entscheidung unterstützen.

Ich schwöre Dir, der untere Code steht bei mir in der automatisch generierten "MyModel.Context.cs"-Datei (also erst wenn man die TT-Datei aufklappt); nicht jedoch in der MyModel.Context.tt-Datei (diese beginnt mit einem "<#") und auch nicht in der MyModel.Designer.cs-Datei (die nur einen Kommentar enthält):


public partial class MyEntities : DbContext
     {
         public MyEntities()
             : base("name=MyEntities")
         {
         }
         ..... 

Aber vielleicht hast Du das ja gemeint mit TT-Datei, da sie darunter angezeigt wird?

a) muss man wissen, was sie tun und b) muss man wissen, wie der generierte Inhalt anzusprechen ist. Beide ist bei Dir wohl eher nicht der Fall.

Da gebe ich Dir allerdings Recht. Ich versuche mich aber damit zu beschäftigen. Nun schon seit einer Woche.

Du kannst problemlos den generierten Context links liegen lassen und eine eigene Klasse erstellen, die von DbContext erbt und die nutzen - nach Deinen wünschen. Wo ist das Problem?

--> Das ist ein sehr guter Hinweis. Wenn ich wirklich den grafischen Designer ignoriere und alles per Hand codiere.

Momentan steht in der MyModel.Context.cs (unterhalb der MyModel.Context.tt) u. a. folgendes:


         protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet<Kunde> Kunde { get; set; }
        public virtual DbSet<Lieferant> Lieferant { get; set; }
        ...

--> Ich müsste faktisch nur die obere OnModelCreating-Methode füllen sowie bei jedem Einfügen einer neuen Tabelle das DbSet unten ergänzen.

  • Kannst Du einen Link empfehlen, wo das richtig gut erklärt wird? Ich würde mich da gerne - trotz Zeitmangel - richtig einarbeiten.

Besten Dank!

Mfg
Michael

PS: Ich stelle nur Fragen, wenn ich in Büchern, im Web und in Foren nichts gefunden habe. Dumme Fragen bitte ich zu entschuldigen!

:] VISUAL STUDIO 2017 + .NET FRAMEWORK 4.5 + SQL-Server 2012 :]

P
1.090 Beiträge seit 2011
vor 10 Jahren

Hi m.grauber,

schon das dich das mit dem ConecteString auf eine Idee gebracht hatte und funktioniert.
Ich hatte da aber eher im hinterkopf, dsa du bei deinen ConneCtionString die Metadaten vergessen hast (csdl, ssdl ,msl).

Also Tuturiel hab ich jetzt das gefunden, ob es gut ist kann ich aber nicht sagen.

MFG
Björn

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

M
m.grauber Themenstarter:in
343 Beiträge seit 2010
vor 10 Jahren

Hallo Palin!

der Link und die Unterlinks waren sehr gut und ich habe sogar das Testprojekt umgesetzt.

Allerdings wurden diese Entitäten bereits durch den EDMX-Designer korrekt erzeugt.

Das Problem war, dass der Connectionstring zwar richtig war, aber zuerst initialisiert und dann der .ConnectionString gesetzt wurde. Bei ObjectContext war das bisher kein Problem, nur DbContext will es direkt im Konstruktor haben.

Also läuft die Connection ersteinmal!

Nochmals Danke an alle! 👍 👍 👍

Mfg
Michael

PS: Ich stelle nur Fragen, wenn ich in Büchern, im Web und in Foren nichts gefunden habe. Dumme Fragen bitte ich zu entschuldigen!

:] VISUAL STUDIO 2017 + .NET FRAMEWORK 4.5 + SQL-Server 2012 :]