CollaboratingPlatypus / PetaPoco

Official PetaPoco, A tiny ORM-ish thing for your POCO's
Other
2.07k stars 601 forks source link

How to inject Petapoco into IOC in Asp. Net 6 #708

Closed hdwubinw closed 11 months ago

hdwubinw commented 11 months ago

How to inject Petapoco into IOC in Asp. Net 6

Ste1io commented 11 months ago

The main class, Database, is designed to handle disconnection/cleanup when leaving scope. If you want to inject it into a container, you'll need to be sure you know what the lifetime of that container is, and ensure the instance is closed when you're finished.

This response to an earlier question might help, and this issue thread also. If your use case is different, provide some more details.

hdwubinw commented 11 months ago

I did it this way, I'm not sure if it's possible because I'm at the beginner level. Is there an official way to write it?

builder.Services.AddSingleton( DatabaseConfiguration.Build() .UsingConnectionString(builder.Configuration.GetConnectionString("DefaultConnection")) .UsingProvider()); builder.Services.AddScoped((db) => db.GetService().Create());

Ste1io commented 11 months ago

I edited your reply, but in the future, when including code, please use the GitHub web interface and surround the code with markdown code blocks so it's readable for others to help.

That said, here's a slightly modified version of your code. Yours should work also, but these changes will help your code be more robust and better communicate intent.

// IDatabaseBuildConfiguration only needs created once, so AddSingleton works fine
builder.Services.AddSingleton<IDatabaseBuildConfiguration>(DatabaseConfiguration.Build()
    .UsingConnectionString(builder.Configuration.GetConnectionString("DefaultConnection"))
    .UsingProvider<MySqlConnectorDatabaseProvider>());

// IDatabase will use a new instance for each HTTP request, created from your configuration, so AddScoped is appropriate
builder.Services.AddScoped<IDatabase>(provider => provider.GetRequiredService<IDatabaseBuildConfiguration>().Create());
  1. Changed db to provider; this is for code readability (x would work also, as far as the compiler is concerned). You get the service from the ServiceProvider, not your database (db).
  2. Changed GetService<T> to GetRequiredService<T> (more info here under section 2.2). The difference is that the former, which you were using, simply returns null if the requested service cannot be resolved by the IServiceProvider interface. The latter, available in .NET 6 or higher, provides a stricter contract by throwing if it's unable to get the service.

This writeup on Medium does a fairly good job at explaining things also, along with the official ASP.NET Core 6 documentation.

hdwubinw commented 11 months ago

Okay, thank you very much. I'll give it a try

从 Windows 版邮件https://go.microsoft.com/fwlink/?LinkId=550986发送

发件人: Stelio @.> 发送时间: 2023年10月24日 19:14 收件人: @.> 抄送: @.>; @.> 主题: Re: [CollaboratingPlatypus/PetaPoco] How to inject Petapoco into IOC in Asp. Net 6 (Issue #708)

I edited your reply, but in the future, when including code, please use the GitHub web interface and surround the code with markdown code blocks so it's readable for others to help.

That said, here's a slightly modified version of your code. Yours should work also, but these changes will help your code be more robust and better communicate intent.

// IDatabaseBuildConfiguration only needs created once, so AddSingleton works fine

builder.Services.AddSingleton(DatabaseConfiguration.Build()

.UsingConnectionString(builder.Configuration.GetConnectionString("DefaultConnection"))

.UsingProvider<MySqlConnectorDatabaseProvider>());

// IDatabase will use a new instance for each use, created from your configuration, so AddScoped is appropriate

builder.Services.AddScoped(provider => provider.GetRequiredService().Create());

  1. Changed db to provider; this is for code readability (x would work also, as far as the compiler is concerned). You get the service from the ServiceProvider, not your database (db).
  2. Changed GetService to GetRequiredService. The difference is that the former, which you were using, simply returns null if the requested service cannot be resolved by the IServiceProvider interface. The latter provides a stricter contract by throwing if it's unable to get the service.

― Reply to this email directly, view it on GitHubhttps://github.com/CollaboratingPlatypus/PetaPoco/issues/708#issuecomment-1777005595, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AXMZCK73C62CXEOLC7BX3YDYA6PJBAVCNFSM6AAAAAA6LUZ6N2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZXGAYDKNJZGU. You are receiving this because you authored the thread.Message ID: @.***>