【发布时间】:2020-09-26 15:15:03
【问题描述】:
我在使用 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>() 是最好用的。
可能只有我有这个问题,但文档似乎缺少一些关于如何完成这个看似简单的任务的提示。
到目前为止,我查看了以下网站:
-
https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/intro?view=aspnetcore-3.1&tabs=visual-studio
- 但此示例中没有使用任何服务。
-
https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext#using-dbcontext-with-dependency-injection
- 虽然解决方案似乎只是将上下文作为参数添加到服务的构造函数中,但我似乎无法在任何调用期间找到如何添加此参数。
-
https://stackoverflow.com/a/48698290
- 我不能 100% 确定这是否是我正在寻找的,但如果结果是这样,我想就如何实现这一点提供一些提示。
-
asp.net core access dbcontext within class
- 这里使用了一些中间件,我想这不是我想要的。
-
https://stackoverflow.com/a/44484724/2986756
- 这是一个使 DbContext 瞬态的选项,也不是我想要的。
-
https://stackoverflow.com/a/37511175
- 这里的数据库被放置在一个单例中。虽然我可以使用它,但我认为我不应该使用它。
【问题讨论】:
-
用
LeaderBoardService(ApplicationDbContext context)向LeaderBoardService添加一个构造函数,将上下文保存到成员变量_context中。将LeaderBoardService注册为 Transient 或 Scoped(检查它们之间的区别),从方法_context.YourTable访问上下文。 -
另外,log4net 与
Microsoft.Extensions.Logging集成。您真的不应该直接使用ILog或LogManager.GetLogger。相反,您应该添加log4net 服务并将ILogger<LeaderBoardService>注入到您的构造函数中。 nuget.org/packages/…
标签: c# entity-framework asp.net-core blazor-server-side