两个ASP.NET Core项目之间的依赖关系注入

时间:2020-07-20 12:01:57

标签: c# asp.net asp.net-core .net-core entity-framework-core

我目前正在使用ASP.NET Core开发一个Web应用程序,并使用Entity Framework Core处理数据库。我的VS解决方案中有两个项目; WebApp(主应用程序)和DatabaseHandler(EF Core处理程序)。由于我使用的是MySQL数据库,因此我已经将Entity Framework Core和Pomelo软件包一起安装了。

我一直在遵循Microsoft文档来设置EF Core,连接字符串等,并且一切正常。我能够进行迁移,进行更新以及对数据库进行处理。但是,我不确定我是否做得正确,因为最新的EF Core教程使用了依赖注入,因此我并不熟悉。

现在,我要将DbContext对象作为参数从WebApp传递给DatabaseHandler,因为我希望所有与数据库相关的内容仅存在于DatabaseHandler中。这可行,但是是否可以从另一个项目中调用函数并共享DbContext对象而不将其作为参数传递呢?我可能没有很好地解释它,希望我的代码能更好地解释它。

WebApp / Startup.cs:
这是我从appsettings.json加载连接字符串的地方。

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContextPool<DataContext>(
        options => options.UseMySql(Configuration.GetConnectionString("DefaultConnection")
    ));

    services.AddRouting(options => options.LowercaseUrls = true);
    services.AddControllersWithViews();
}

WebApp / HomeController.cs:
在这里,我从DatabaseHandler项目中调用GetAllChallenges()函数,同时还将DataContext对象作为参数传递。这就是我要避免的事情!

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    private readonly DataContext db;

    public HomeController(ILogger<HomeController> logger, DataContext _db)
    {
        _logger = logger;
        db = _db;
    }

    public IActionResult Challenges()
    {
        List<Challenge> ChallengesList = DatabaseHandler.HandleChallenges.GetAllChallenges(db);
        return View(ChallengesList);
    }
}

DatabaseHandler / DataContext.cs:
这是我初始化实体类的地方。

public class DataContext : DbContext
{
    public DataContext(DbContextOptions<DataContext> options) : base(options) { }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { }

    // Tables
    public DbSet<User> Users { get; set; }
    public DbSet<Challenge> Challenges { get; set; }

    // Data seeding
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Seed();
    }
}

DatabaseHandler / HandleChallenges.cs:
这是我拥有所有数据库功能的地方。结果返回到WebApp项目内的控制器。

public class HandleChallenges
{
    public static List<Challenge> GetAllChallenges(DataContext db)
    {
        var Data = db.Challenges;
        List<Challenge> ChallengesList = Data.ToList();
        return ChallengesList;
    }
}

我已经研究了依赖注入,但是我不确定如何在两个项目之间使用它。是否有一种不太复杂的方式来实现这一目标,也许根本不需要使用DI?我很满意,只要我每次需要从DatabaseHandler调用函数时都不需要将DataContext对象作为参数传递即可。

有人可以帮助我理解吗?提前非常感谢!

2 个答案:

答案 0 :(得分:2)

您可以使用我已经使用过很多次的“选项”模式。尽管您使用的是数据库,但它的效果仍然很好。通过依赖注入,您可以从多个项目中进行访问。阅读有关选项模式(https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1)的文档很有用,但我还将为您提供示例:

  1. 首先创建一个模型来存储连接字符串,dbName等。请记住将其添加到主项目(例如Web Api)之外的库中:

     public class NameOfYourProject_ApiDbSettings : IIMTTApiDbSettings
     {
         public NameOfYourProject_ApiDbSettings()
         {
         }
         public string CollectionName { get; set; }
         public string ConnectionString { get; set; }
         public string DatabaseName { get; set; }
     }
    
    
    public interface I_NameOfYourProject_ApiDbSettings
    {
     string CollectionName { get; set; }
     string ConnectionString { get; set; }
     string DatabaseName { get; set; }
    }
    
  2. 第二,您可以将其用于所有项目:

        services.Configure<NameOfYourProjectApiDbSettings>(options =>
         {
             options.ConnectionString
                 = Configuration.GetSection("NameOfYourProjectDbSettings:ConnectionString").Value;
             options.DatabaseName
                 = Configuration.GetSection("NameOfYourProjectDbSettings:DatabaseName").Value;
         });
    
  3. 然后您可以在多个项目中使用它。 (记住要为您的模型添加引用->点1。我将模型始终与存储库一起使用)我将为您提供使用MongoDb的示例:

     private readonly IMongoDatabase _database = null;
    
     public SomeObjectContext(IOptions<IMyProjectDbSettings> settings)
     {
         var client = new MongoClient(settings.Value.ConnectionString);
         if (client != null)
             _database = client.GetDatabase(settings.Value.DatabaseName);
     }
    
     public IMongoCollection<MyModel> MyModels
     {
         get
         {
             return _database.GetCollection<MyModel>("MyModels");
         }
     }
    

答案 1 :(得分:1)

您需要从类中提取接口(请注意该方法不再是静态的)并为上下文添加构造函数:

public interface IHandleChallenges
{
    List<Challenge> GetAllChallenges();
}

public class HandleChallenges : IHandleChallenges
{
    public HandleChallenges(DataContext context)
    {
        db = context;
    }
    
    private DataContext db;
    
    public List<Challenge> GetAllChallenges()
    {
        var Data = db.Challenges;
        List<Challenge> ChallengesList = Data.ToList();
        return ChallengesList;
    }
}

然后将其注册为服务:

 services.AddScoped<IHandleChallenges, HandleChallenges>();
 

您的控制器现在在其构造函数(而不是上下文)中收到 this 类:

private IHandleChallenges _challengeHandler;
public HomeController(ILogger<HomeController> logger, IHandleChallenges challengeHandler)
{
    _logger = logger;
    _challengeHandler = challengeHandler;
}

并从操作中调用它:

public IActionResult Challenges()
{
    List<Challenge> ChallengesList = _challengeHandler.GetAllChallenges();
    return View(ChallengesList);
}