我目前正在使用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对象作为参数传递即可。
有人可以帮助我理解吗?提前非常感谢!
答案 0 :(得分:2)
您可以使用我已经使用过很多次的“选项”模式。尽管您使用的是数据库,但它的效果仍然很好。通过依赖注入,您可以从多个项目中进行访问。阅读有关选项模式(https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.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; }
}
第二,您可以将其用于所有项目:
services.Configure<NameOfYourProjectApiDbSettings>(options =>
{
options.ConnectionString
= Configuration.GetSection("NameOfYourProjectDbSettings:ConnectionString").Value;
options.DatabaseName
= Configuration.GetSection("NameOfYourProjectDbSettings:DatabaseName").Value;
});
然后您可以在多个项目中使用它。 (记住要为您的模型添加引用->点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);
}