Als Nachtrag, hab es über Automapper geschafft.
Aber nicht das ganze Objekt direkt, sondern die Properties einzelnt zu mappen.
Man braucht dafür das Nuget Package von Automapper 'AutoMapper.Extensions.ExpressionMapping'.
Und dann muss man noch beim hinzufügen des Automappers im Service die Methode aufrufen
automapper.AddExpressionMapping();
//So sieht das dann ganz aus
services.AddAutoMapper((serviceProvider, automapper) =>
{
automapper.AddExpressionMapping();
automapper.AddProfile<AutoMapping>();
}, typeof(ApplicationDbContext).Assembly);
Das hatte ich davor auch schon alles.
Was ich nun mache, das ich die einzelnen Properties vom Specification Objekt durch gehe und diese mappe:
Mit Automapper schaffe ich es nicht, es zu mappen. Der Wert ist immer null. (Criteria)
Deshalb manuell mappen.
Wie mappt man eine Expression? I dont know => google.
Wobei ich bei der _parameter Variable das 'c' entfernt habe.
Mapping erfolgreich.
1. Bild im Anhang: So sieht es dann im Debugger aus.
Lass ich die Expression nun gegen die Db laufen, erhalte ich eine InvalidOperationException, sobald ich auf den Entites mit Where und dem Criteria filtere.
Message:
The LINQ expression 'DbSet<Category>()
.Where(c => x.Id == __idToGet_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See [url]https://go.microsoft.com/fwlink/?linkid=2101038[/url] for more information.
In der Message steht "c => x.Id....".
Ich gehe davon aus, dass es an dem "c" liegt. Aber woher kommt das?
P.S.: Ich weiß wie Expressions oberflächlich funktionieren, aber so genau, wie man diese mappt, woraus die konkret bestehen weiß ich nicht. Deswegen habe ich vorerst die Methoden aus dem SO Beitrag 1:1 übernommen.
Service: Erstellt einen default HttpClient.
service.GetServerUrlAsync(): ruft die oben angegeben Endpoint Adresse auf, wo ich als response die Session ID und die URL zum hochladen bekomme.
Response hat einen 200er.
Im Content steht nur:
<h1>Internal Server Error</h1>\n<p>The server encountered an internal error or\nmisconfiguration and was unable to complete\nyour request.</p>
Übersehe ich etwas? Oder fehlt irgendetwas, was man bei dem Request nicht sieht?
Habt Ihr eine bessere Idee, bzw. was mache ich falsch?
Grüße und schöne Weihnachten :)
P.S.: Es handelt sich um einem Imagehoster. Die Variante mit dem WebClient liefert lediglich einen String mit der URL zu dem hochgeladenen Foto. Die Variante mit dem HttpClient liefer ebenfalls eine URL zurück, nur wenn ich diesen aufrufe, kommt ein leeres Bild vom Hoster. Quasi "Image not Found" Bild.
@Th69 habe ich nach deiner Antwort auch versucht. Ändert nichts daran.
Hab aber herausgefunden das er "\t" nicht mag. Habe jetzt manuell mit Whitespaces gefüllt und es geht halbwegs.
ich wusste nicht, in welchen Unterbereich ich es posten sollte. Falls es hier falsch ist, gerne verschieben.
Ausgangssituation:
- Console Application .NET 5
- Downloader von Files (in verschiedenen Threads)
Ziel:
- Anzeigen vom aktuellen Status des Downloads
(Name der Datei, wie viel wurde heruntergeladen in %, wie viel wurde heruntergeladen in double,
wie groß ist die Datei)
Versuchte Lösungen:
Console.SetCursorPosition(x, y);
Console.Write("\rText");
- Überschreiben der beschriebenen Zeilen mit Leerzeilen, weil das rewrite mit \r wohl laut stackoverflow nicht alle characters löscht.
Hier einmal der Code dazu:
public static void LogDownload(ITransferProgress progress, DownloadItem downloadItem)
{
string filename = Path.GetFileName(downloadItem.OutputPath);
Console.SetCursorPosition(0, downloadItem.CursorTopPosition);
string outputString = $"{filename}\t\t\t\t{progress.PercentComplete:P}\t|\t" +
$"{progress.CurrentFileSize:0.##} {progress.CurrentFileSizeSuffix} / {progress.FileSize:0.##} {progress.FileSizeSuffix}";
//ClearText(outputString, 0, downloadItem.CursorTopPosition);
Console.Write($"\r{outputString}");
}
private static void ClearText(string text, int x, int y)
{
Console.SetCursorPosition(x, y);
for (int i = 0; i < text.Length; i++)
{
Console.Write(" ");
}
Console.SetCursorPosition(x, y);
}
Das ganze funktioniert auch halbwegs (flackert dann nur), wenn es nur eine Zeile ist. Nur wenn mehrere Zeilen geschrieben werden,
a) flackerts
b) der Text ist irgendwo, wo er nicht hin soll und doppelt
Hier auch einmal der Output mit mehreren Downloads. Output ist genau so, wie der oben genannte Code.
Wisst Ihr wie man das besser / performanter, ohne flackern und das alles richtig angezeigt wird umsetzen kann?
Ich gehe davon aus, dass ich zu viel neu schreibe, aber dann fällt mir auch keine andere Lösung ein.
Also entferne mal den Konstruktor mit den Options, ich könnte mir vorstellen, dass es dann funktioniert - vorausgesetzt, der DbContext kann sich selber konfigurieren. Besser wäre aber, Du nutzt die Factory und ziehst die Konfiguration raus..
Das scheint es noch ein Problem mit Interfaces zu geben, was du ggf. haben könntest.
Das Problem habe ich gar nicht. Also ich nutze gar keine Interfaces oder sonst was.
Die User Klasse hat nur 3 Properties und die ganze Class Library hat 2 Klasssen (User und ApplicationDbContext).
Es gibt einen "Workaround" dafür, indem man in der gleichen Assembly eine ContextFactory hat:
public class ContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext CreateDbContext(string[] args)
{
DbContextOptionsBuilder<ApplicationDbContext> optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
return new(optionsBuilder.Options);
}
}
Damit lassen sich nun Migrationen erstellen.
Aber würde das gerne ohne den "Workaround" machen.
ich migriere gerade meine Projekte auf .NET 5 und so auch EF Core.
Nun ist mir ein Problem bei der Erstellung der Migrationen aufgefallen.
Ausgangssituation zum erstellen der Migrationen.
1. .NET 5 Class Library mit dem DbContext
Installierte NuGets:
Microsoft.EntityFrameworkCore 5.0.0
Microsoft.EntityFrameworkCore.SqlServer 5.0.0
public class ApplicationDbContext : DbContext
{
#region DbSets
public DbSet<User> Users { get; set; }
#endregion
public ApplicationDbContext(DbContextOptions options) : base(options)
{
}
public ApplicationDbContext() : base()
{
}
}
2. Test Projekt .NET 5 was ich als Start Projekt ausgewählt habe und via der Package Manager Console
add-migration Initial
ausführe. (Default Projekt ist die Class Library).
Bis meinen installierten NuGet Versionen von 3.1.8 funktionierte es auch, weil das Test Projekt ausführbar ist.
Nach updaten auf .NET 5 erhalte ich folgende Fehlermeldung:
Fehler
PM> add-migration Initial
Build started...
Build succeeded.
Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
In den Breaking Changes von EF Core 5 habe ich keine Änderungen gefunden, die das behindern sollten.
In den Github Issues von efcore habe ich den Artikel gefunden, dass es bei einem funktioniert, der das sagt:
Zitat
You can add an option such as sqlOptions.MigrationsAssembly();
Habe ich auch gemacht, gleiche Fehlermeldung. Bzw. erwartet die Methode einen Parameter, die Assembly. Habe ich ebenfalls hinzugefügt, aber ändert nichts.
Zum aufrufen einer neuen Form, erstellst du ein Objekt von der Form.
Dann kannst du beispielsweise über den Konstruktor Parameter übergeben oder über public Properties die du dann setzen kannst.
wenn man keine Antworten erhält, versteht man entweder das Problem/die Frage nicht oder weiß keine Lösung.
Ersteres weiß ich nicht, wie ich es noch besser Beschreiben soll, weil ich mMn sehr viele Informationen liefere mit einem Git Repo, worin man das Problem reproduzieren kann.
Aber wer auch immer den Titel geändert hat, hat das Problem nicht verstanden.
Der Mapper wirft keine Exception, sondern EF Core beim Hinzufügen der Entity zum DbSet.
Hoffe trotzdem, dass jemanden evtl. was einfällt, weil mir tut es nicht, obwohl ich mich bis dato immer noch damit beschäftige.
Zum Thema.
Ich hatte immer nur eine normale Bankkarte und bin dank eines Kollegens auf "Vivid" aufmerksam geworden.
Prepaid Kreditkarten System. Habe eine virtuelle und eine physische.
Ich mache soviel wie möglich über die App davon, weil es einfach viel übersichtlicher und schneller ist, als mein Girokonto.
Also ja, ich nutze überall wo ich kann meine Kreditkarte.
ich verwende AutoMapper um meine Entitäten von und zu DTO Entitäten zu mappen, funktioniert auch ohne Probleme.
Das Problem kommt erst, wenn ich dann mit der gemappten Entität arbeite.
Ich habe eine Translation Entity und eine Language Entity. (1:n)
Language hat n Translations.
Language language = applicationDbContext.Languages.FirstOrDefault(x => x.Name == "pl-t");
LanguageDTO mappedLanguage = new LanguageDTO();
mapper.Map(language, mappedLanguage);
//Input from ui
TranslationDTO translation = new TranslationDTO
{
Identifier = "dtoTrans",
Text = "dtoTrans",
Language = mappedLanguage, //Does not work
LanguageId = mappedLanguage.Id, //Works
Id = Guid.NewGuid()
};
Translation trans = new Translation();
mapper.Map(translation, trans);
applicationDbContext.Translations.Add(trans); // Exception
Im Code Beispiel hole ich mir eine Language aus der Datenbank (Könnte auch eine neue erstellen, ist aber irrelevant) und mappe diese zu einem DTO.
Erstelle dann eine DTO Translation Entity (kommt bspw. von der UI) und würde dann im normalen Code die Navigation Property "Language" setzen und dann in der Datenbank erstellen.
Was ohne Mappen auch wunderbar funktioniert, mit Mapping erhalte ich diese Fehlermeldung:
Fehler
The instance of entity type 'Language' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
Hab dazu den Thread auf Stackoverflow gefunden und den Aufruf der Map Methode wie in der Antwort geändert. Hatte das genau so wie sein 1. Beispiel (aus der Antwort).
Hilft auch nicht.
Setze ich aber nur die ID anstatt die ganze Entity, funktionierts.
Ich finde aber zu dem Problem explizit auch keine Lösung, wie man das Mappen umstellen soll.
Man kann die Entity dann noch De/-Attachen aber ist dann auch wieder mehr Aufwand.
Hier ist einmal das Git Repo. Ist ein Test Projekt, was diesen Fehler produziert.
Als explizite Frage nochmal. Was genau mache ich falsch bzw. was muss ich ändern, dass die Fehlermeldung nicht mehr erscheint?
Meine Frage ist jetzt, ob man Visual Studio so einrichten kann das ich diese Konsolenausgabe in Visual Studio direkt als Fenster nutzen kann ohne das sich ständig etwas öffnet oder schließt?
Es gibt unter den Options => Debugging => General den Punkt "Automatically close the console when debugging stops". Damit bleibt das Konsolenfenster immerhin offen sobald VS das Debugging wieder beendet.
Zitat von snapCode
Kann ich GIT weiter verwenden um einen Commit, Snapshot und einen Brach zu erstellen?
Siehe @Taipi88 Kommentar. Ich nutze die VS Git Integration. Sobald der Ordner mit einem Git Repo verbunden ist, kannst du unter dem Fenster "Team Explorer" alle Git Funktionen nutzen.
ich habe mich gerade hier angemeldet, da ich mich entschlossen habe C# mal aus zu probieren.
Dann lese ich direkt hier im Forum über das vermutliche ableben von C#?
Ist ja nicht direkt vertrauenserweckend.
Wie du es aus diesem Thread, dem ganzen Forum und den Twitter Antworten entnehmen kannst, wird C# uns noch lange begleiten.
Ich wollte nur eine Diskussion zu dem Artikel anstoßen und die Meinung der User hören.
Und damit nicht signalisieren, dass C# auf kurz oder lang "aussterben" wird.
Laut Avision bzw. Nadine Riederer wird C# auf kurz oder lang von Microsoft nicht mehr supported.
Man solle doch auf Java umsteigen.
Wie steht ihr zu der Aussage von Frau Riederer?
Meine Meinung dazu ist, durch die ganzen Änderungen die Microsoft derzeit macht (dotnet 5, Blazor) wird C# lange erhalten bleiben und halte die Aussage für kompletten Schwachsinn.
Um auf dein Beispiel zurückzukommen:
Wenn BLL1 die BLL2 braucht - dann bekommt sie diese eben per Konstruktor. In der eigentlichen Anwendung (dort in der Startup z.B.) kann man das dann gerne als Singleton via DI umsetzen[...]
Moin Taipi,
dass ist ja mein Plan, dass ich die einzelnen BLL via Konstruktor erhalte, was ja möglich ist.
Das Problem ist nur, dass ich irgendwo die ganzen Singletons registrieren muss. Ja dies wird eigentlich in der Startup Klasse gemacht oder halt da, wo das Programm gestartet wird.
Nur ist das Beispiel oben von mir eine Library die ich via NuGet an meine Projekte verteile. Und will dennoch DI nutzen können.
Da komm ich dann zu meiner letzten Frage zu Abt
Zitat von duesmannr
Also meinst du, dass ich bei der Dokumentation dem Entwickler sagen soll
Dass er irgendein DI Framework nutzen muss und dann eine Liste mit Interfaces und Klassen dazu schreibe, die registriert werden müssen?
Das ich dem Entwickler(mir) dann eine Liste mit Singletons gebe, die registriert werden müssen, damit die Library funktioniert.
Und das ist auch keine schöne Lösung, deswegen hatte ich hier erhofft eine Lösung zu finden :)