Injizierter scoped Service in EF Core DBSet in Hotchocolat 15: Der Scoped -Service kann nicht vom Root -Anbieter gelöst
Posted: 22 Feb 2025, 11:52
Ich habe kürzlich mein Backend GraphQL -Backend mit EF Core und Hotchocolat von Version 12.x.x bis 15.0.3 aktualisiert. Build/Start funktioniert gut. Ich habe jedoch Probleme beim Abfragen, da der Fehler unerwarteter Ausführungsfehler geworfen wird. Ich verwende einen httpaccessor und extrahiere JWT -Informationen daraus und speichere sie in den Service iRequestIdentity . Dies wurde seitdem in den DBContext injiziert, wo ich zwei Dinge damit mache:
Globale Abfragefilter auf die Entitäten anwenden
Implementieren Sie eine "geändert nach" Logik, wobei die Benutzer -ID nach jedem Schreiben auf einen Datensatz aktualisiert wird. < /li>
< /ol>
Es gab dort Eine Änderung in HC15 In der Art und Weise, wie DI Scope und EF -Registrierung jetzt durchgeführt werden. Ich vermute, dass dies die Hauptursache ist. Ich kann den Fehler beheben, aber dafür muss ich 1) und 2) oben entfernen, was ich wirklich vermeiden möchte. < /P>
Hier ist meine Argumentation und was ich bis jetzt getan habe - Dies sind die relevanten Dienste und die DI-Registrierung: < /p> und für 2) in den Savechanges -Methoden. Beachten Sie auch, dass ich IrequestIdentität in den ctor des dbSet inject inject inject inject
injiziere.
Dies funktioniert jedoch auch nicht. Die Anfragen kehren beide erfolgreich zurück. Aber ich verliere meine Anforderungen 1) und 2) oben. Während ich 1 ausgleichen könnte, indem ich nur zusätzliche .where () Filter in der Abfrage hinzufügt, habe ich keine Ahnung, wie ich 2), ohne etwas in den DBSet .
Haben Sie eine Idee, wie ich diese Funktionsweise machen könnte? Ihre Gedanken dazu und jedes Feedback werden sehr geschätzt!
Globale Abfragefilter auf die Entitäten anwenden
Implementieren Sie eine "geändert nach" Logik, wobei die Benutzer -ID nach jedem Schreiben auf einen Datensatz aktualisiert wird. < /li>
< /ol>
Es gab dort Eine Änderung in HC15 In der Art und Weise, wie DI Scope und EF -Registrierung jetzt durchgeführt werden. Ich vermute, dass dies die Hauptursache ist. Ich kann den Fehler beheben, aber dafür muss ich 1) und 2) oben entfernen, was ich wirklich vermeiden möchte. < /P>
Hier ist meine Argumentation und was ich bis jetzt getan habe - Dies sind die relevanten Dienste und die DI-Registrierung: < /p>
Code: Select all
public interface IRequestIdentity
{
Guid TenantId { get; init; }
Guid UserId { get; init; }
}
public record RequestIdentity(Guid TenantId, Guid UserId) : IRequestIdentity;
builder.Services.AddScoped(sp =>
{
HttpContext? httpContext = sp.GetRequiredService().HttpContext;
ArgumentNullException.ThrowIfNull(httpContext);
ClaimsPrincipal user = httpContext.User;
return new RequestIdentity(user.TenantId, user.Id);
});
builder.Services.AddDbContext(opt =>
{
string dbPath = builder.Configuration.GetRequiredValue("dbPath");
opt.UseSqlite($"Data Source={dbPath}");
});
< /code>
Und dies ist mein EF -Kerndatenmodell. Beachten Sie das Verhalten für 1) in den OnModelCreating
injiziere.
Code: Select all
public record Animal
{
public Guid TenantId { get; set; }
public Guid ChangedBy { get; set; }
[MaxLength(50)] public string Name { get; set; }
}
public class DataContext : DbContext
{
public DbSet Animals { get; init; } = null!;
public readonly IRequestIdentity RequestIdentity;
public DataContext(DbContextOptions options, IRequestIdentity reqId) : base(options)
{
RequestIdentity = reqId;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(e =>
{
e.ToTable("Animals");
e.HasQueryFilter(a => a.TenantId == RequestIdentity.TenantId);
});
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
// updated ChangedBy property
return base.SaveChanges(acceptAllChangesOnSuccess);
}
}
< /code>
Hier ist die heiße Schokoladenschicht auf dem EF -Kern. Das Modell und das Schema werden im GraphQL Nitro Explorer gut angezeigt.public partial class Query
{
public IQueryable GetAnimals(DataContext ctx)
=> ctx.Animals;
}
< /code>
query {
animals {
id
}
}
< /code>
Ausführen dieser Abfrage führt jetzt zu einem Fehler < /p>
{"Fehler": [
{"Nachricht ":" Unerwarteter Ausführungsfehler ",
" Positionen ": [{" Zeile ": 2," Spalte ": 3}],
" Pfad ": [" Tiere "] }], "data": null}
Nach der offiziellen HC -Dokumentation hat sich die Art und Weise, wie EF Core verdrahtet ist />
builder.Services.AddDbContextFactory(opt =>
{
string dbPath = builder.Configuration.GetRequiredValue("dbPath");
opt.UseSqlite($"Data Source={dbPath}");
});
//...
builder.Services.AddGraphQLServer().RegisterDbContextFactory();
< /code>
Die gleiche Abfrage führt dann zu diesem Fehler < /p>
{"Fehler":
[{"Nachricht": "Unerwarteter Ausführungsfehler",
"Positionen": [{"Zeile": 2, "Spalte": 3}], "Pfad": ["Animals"], "Erweiterungen": {"Nachricht": "Kann nicht den skopierten Service 'irequestidentity' vom Root -Anbieter beheben.", "Stacktrace": "..."}}], "Daten": null}
< /blockquote>
afaik, der dbContextFactory < /code> ist ein Singleton, in dem ich versuche, abzuleiten Scoped-Service, der nicht funktioniert. Dort habe ich auch mit dem Werksansatz versucht, der in der Dokumentation festgelegt ist: < /p>
public partial class Query
{
public IQueryable GetAnimalsWithFactory(IDbContextFactory ctxFactory)
=> ctxFactory.CreateDbContext().Animals;
}
Haben Sie eine Idee, wie ich diese Funktionsweise machen könnte? Ihre Gedanken dazu und jedes Feedback werden sehr geschätzt!