.Net 7 C# DI:在存储库的类构造函数中引用 AppDbContext(其中 AppDbContext 不可访问)

问题描述 投票:0回答:1

在我的解决方案中,我有 4 个项目。

  1. App.Web => .net 7 MVC 项目
  2. App.Api => Another .net 7 Api project (both under the same solution)
  3. 应用程序域
  4. App.Repository

目前(可能会发生变化,具体取决于答案)我在“域”层中创建了上下文创建/定义和 EF 迁移。

App.Web(以及 App.API)需要使用“通用”DbContext(它们都引用“域”至极引用“存储库”)。

我在 program.cs(复制在下面)中创建/配置 DI,但我的问题是我无法从存储库访问 UsersDbContext,因为它在“域”中。

一个解决方案可能是创建另一个名为 App.Data 的单独项目,其中仅定义上下文,“Web”、“Api”和“Repository”将引用该项目以访问上下文,但我不确定这是最好的解决方案。

这是我的程序.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();

#region swagger
//builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(option =>
{
  option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo API", Version = "v1" });
  option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
  {
    In = ParameterLocation.Header,
    Description = "Please enter a valid token",
    Name = "Authorization",
    Type = SecuritySchemeType.Http,
    BearerFormat = "JWT",
    Scheme = "Bearer"
  });
  option.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type=ReferenceType.SecurityScheme,
                    Id="Bearer"
                }
            },
            new string[]{}
        }
    });
});
#endregion

#region jwt data
var validIssuer = builder.Configuration["JWT:ValidIssuer"];
var validAudience = builder.Configuration["JWT:ValidAudience"];
var issuerSigningKey = builder.Configuration["JWT:IssuerSigningKey"];
#endregion

if (validIssuer != null && validAudience != null && issuerSigningKey != null)
{
  #region jwt
  builder.Services
  .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  //.AddAuthentication(options =>
  //{
  //    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
  //    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  //    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
  //})
  .AddJwtBearer(options =>
  {
    options.TokenValidationParameters = new TokenValidationParameters()
    {
      ClockSkew = TimeSpan.FromDays(1),
      ValidateIssuer = true,
      ValidateAudience = true,
      ValidateLifetime = true,
      ValidateIssuerSigningKey = true,
      ValidIssuer = validIssuer,
      ValidAudience = validAudience,
      IssuerSigningKey = new SymmetricSecurityKey(
              Encoding.UTF8.GetBytes(issuerSigningKey)
          ),
    };
  });
  #endregion

  #region DbContext

  //builder.Services.AddDbContext<UsersDbContext>(options =>
  //{
  //  options.UseSqlServer(builder.Configuration.GetConnectionString("SurveyConnection"));
  //});

  //builder.Services.AddDbContext<UsersDbContext>();
  var connectionString = Util.getAppSettingsValue("ConnectionStrings:SurveyConnection");
  if (connectionString == null)
  {
    throw new Exception("SQL connection string is not set in appsettings.json!");
  }
  builder.Services.AddSingleton(new UsersDbContext(connectionString));
  #endregion

  #region neo4j data
  var neo4jServer = builder.Configuration["Neo4J:server"];
  var neo4jUser = builder.Configuration["Neo4J:user"];
  var neo4jPwd = builder.Configuration["Neo4J:pwd"];
  #endregion

  if (neo4jServer != null && neo4jUser != null && neo4jPwd != null)
  {
    #region neo4j
    var client = new BoltGraphClient(new Uri(neo4jServer), neo4jUser, neo4jPwd);
    client.ConnectAsync();
    #endregion

    #region services

    #region repository
    builder.Services.AddSingleton<ISurveysRepository, SurveysRepository>();
    builder.Services.AddSingleton<IBlocksRepository, BlocksRepository>();
    builder.Services.AddSingleton<IQuestionsRepository, QuestionsRepository>();
    builder.Services.AddSingleton<IOptionsRepository, OptionsRepository>();
    builder.Services.AddSingleton<IAnswersRepository, AnswersRepository>();
    #endregion

    #region domain
    builder.Services.AddSingleton<ISurveysDomain, SurveysDomain>();
    builder.Services.AddSingleton<IBlocksDomain, BlocksDomain>();
    builder.Services.AddSingleton<IQuestionsDomain, QuestionsDomain>();
    builder.Services.AddSingleton<IOptionsDomain, OptionsDomain>();
    builder.Services.AddSingleton<IAnswersDomain, AnswersDomain>();
    #endregion

    builder.Services.AddSingleton<IGraphClient>(client);
    //builder.Services.AddSingleton<UsersDbContext>();

    builder.Services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
    builder.Services.AddScoped<TokenService, TokenService>();
    builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
    #endregion

    #region users
    builder.Services
            .AddIdentityCore<IdentityUser>(options =>
            {
              options.SignIn.RequireConfirmedAccount = false;
              options.User.RequireUniqueEmail = true;
              options.Password.RequireDigit = false;
              options.Password.RequiredLength = 6;
              options.Password.RequireNonAlphanumeric = false;
              options.Password.RequireUppercase = false;
              options.Password.RequireLowercase = false;
            }).AddRoles<IdentityRole>().AddEntityFrameworkStores<UsersDbContext>();
    #endregion

    var app = builder.Build();

    // Configure the HTTP request pipeline.
    //if (app.Environment.IsDevelopment())
    //{
    app.UseSwagger();
    app.UseSwaggerUI();
    //}

    #region swagger default page in release mode
    if (!app.Environment.IsDevelopment())
    {
      app.UseSwaggerUI(options =>
      {
        options.SwaggerEndpoint("/swagger/v1/swagger.json", "Surveys Web API");
        options.RoutePrefix = string.Empty;
      });
      app.UseHsts();
    }
    #endregion

    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.UseAuthentication();
    app.MapControllers();

    app.Run();
  }
  else
  {
    throw new Exception("Neo4J is not configured!");
  }
}
else
{
  throw new Exception("JWT is not configured!");
}

问题.cs

public class QuestionsRepository : IQuestionsRepository
{
  private readonly UsersDbContext _context;
  public QuestionsRepository(UsersDbContext context) //=> cannot access UsersDbContext
  {
    _context = context;
  }
  ...
}

关于如何处理这个问题的任何帮助?

c# .net entity-framework dependency-injection dbcontext
1个回答
0
投票

您可以将 DbContext 及其关联的实体放在 App.Data 项目中。

数据库实体是,并且应该与您的域实体不同。领域模型应该只包含他们需要在其中工作的数据。

例如,如果您在数据库中有一个具有以下属性的用户实体:

public class User{
    public Guid ID {get; set;}
    public string Username {get; set;}
    public string Password {get; set;}
    public string EmailAddress {get; set;}
    public string FirstName {get; set;}
    public string LastName {get; set;}
}

您的域逻辑将分为两部分,例如为了显示目的需要名字和姓氏,但在这种情况下不需要密码或 ID,或者只需要用户名和密码即可登录。它不会始终传递完整的数据库实体是有意义的。

© www.soinside.com 2019 - 2024. All rights reserved.