我对ASP.NET核心和实体框架及其所有(其他)组件的使用感到有些困惑。 我正在开发一个简单的网络应用,您可以在其中输入一些数据并让其计算一些统计信息(基本上是strava ultra-light)。
因此,如果我从Visual Studio(2019)打开默认的blazor应用程序,则会得到类似Startup的东西
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using BlazorApp1.Areas.Identity;
using BlazorApp1.Data;
namespace BlazorApp1
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
services.AddSingleton<WeatherForecastService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
类似这样的服务
using System;
using System.Linq;
using System.Threading.Tasks;
namespace BlazorApp1.Data
{
public class WeatherForecastService
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
var rng = new Random();
return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray());
}
}
}
所以我为我的数据添加了一个模型
using Microsoft.AspNetCore.Identity;
using BlazorApp1.Database.Types;
using System.ComponentModel.DataAnnotations;
namespace BlazorApp1.Database.Entity
{
public class Activity
{
public string ActivityData { get; set; }
public ActivityType ActivityType { get; set; }
public float Distance { get; set; }
[Key]
public int Id { get; private set; }
public IdentityUser User { get; set; }
}
}
并将其添加到ApplicationDbContext
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace BlazorApp1.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Activity> Activities { get; set; }
}
}
所以现在我想创建自己的类似于WeatherForecastService的服务,这就是我遇到的问题。
using log4net;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using BlazorApp1.Data.Model;
using BlazorApp1.Database;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace BlazorApp1.Data
{
public class LeaderBoardService
{
private readonly static ILog _logger = LogManager.GetLogger(typeof(LeaderBoardService));
public Task<List<LeaderBoardItem>> GetOverallLeaderboard()
{
//I want to access the database context from here.
return Task.FromResult(result);
}
}
}
此外,我需要将此服务添加到Startup.ConfigureServices()。
到目前为止,我发现我可以使用services.AddScoped<LeaderBoardService>()
,services.AddSingleton<LeaderBoardService>()
和services.AddTransient<LeaderBoardService>()
来完成此任务,看来services.AddScoped<LeaderBoardService>()
是最好的用法。
可能只有我一个问题,但是文档似乎缺少有关如何完成此看似简单的任务的提示。
到目前为止,我查看了以下站点:
答案 0 :(得分:2)
您的LeaderBoardService
应该通过以下方式实现:
public class LeaderBoardService
{
private readonly ApplicationDbContext dbContext;
private readonly ILogger logger;
public LeaderBoardService(ApplicationDbContext dbContext, ILogger<LeaderBoardService> logger)
{
this.dbContext = dbContext;
this.logger = logger;
}
public async Task<List<LeaderBoardItem>> GetOverallLeaderboard()
{
return await dbContext.LeaderBoardItems.ToListAsync();
}
}
关于您的服务生命周期,这取决于您的使用情况,但它的过程决不能超过其内部服务生命周期。因此,您的服务可以是scoped
或transient
,但不能是singleton
,因为您的DbContext声明为scoped
(当然,您绝不能将DbContext声明为singleton
因为并发问题。