这里有很多关于如何执行此操作的文章,但是无论我尝试哪种配置,我似乎都无法获得数据库连接字符串。从Microsoft项目模板自动为Core 2.2配置了startup.cs,据我所知这没有什么问题。我没有使用EF,也不想加载一些第三方的黑匣子以使其正常工作。
这是Startup.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace TestWebApplication1
{
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.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
这是appsettings.json文件:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Data Source=mydbserver;Initial Catalog=mydatabase;Integrated Security=True;Persist Security Info=False;"
}
}
在另一篇文章中,以下应该工作,但不能:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace TestAppWithService
{
public class TestDB
{
string conString = Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString(this.Configuration, "DefaultConnection");
}
}
名为TestDB.cs的文件被设置为可编译,并且要踢一下,我将其放在根文件夹中(与放置类的位置无关:模型,控制器等) 我得到了关键字“ this”在当前上下文中不可用。 (下面有波浪线)。 我不知道如何进行或寻找什么,这里的答案有各种各样的调整,但很多,但是对于MS,这应该可以正常工作。 我是dotnetcore的新手,以为我已经弄清楚了这种依赖注入的内容,但是仍然很困难。
答案 0 :(得分:1)
这不会编译
public class TestDB
{
string conString = Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString(this.Configuration, "DefaultConnection");
}
给出了尝试使用它的上下文。
对IConfiguration
的访问应仅限于合成词根,在本例中为Startup
必须将IConfiguration
注入合成词根之外,这可以看作是一种代码味道,当前的自回答有一些应重构的设计问题。
首先,要解决连接字符串问题,应介绍以下支持的抽象和实现。
public class ConnectionStrings {
public string DefaultConnection { get; set; }
}
public interface IDbConnectionFactory {
IDbConnection Create(string connectionString);
}
public class SqlConnectionFactory : IDbConnectionFactory {
public IDbConnection Create(string connectionString) {
return new SqlConnection(connectionString);
}
}
public interface IDataProvider {
List<DropDownOption> CalcSelectDDSizeAndTilesPerBoxAll();
}
和数据类经过重构以遵循更SOLID的设计方法
public class MyDataProvider : IDataProvider {
static string LastErrorMsg = string.Empty;
private readonly string connectionString;
private readonly IDbConnectionFactory connectionFactory;
public MyDataProvider(ConnectionStrings connections, IDbConnectionFactory connectionFactory) {
this.connectionString = connections.DefaultConnection;
this.connectionFactory = connectionFactory;
}
public List<DropDownOption> CalcSelectDDSizeAndTilesPerBoxAll() {
var options = new List<DropDownOption>();
try {
using (IDbConnection connection = connectionFactory.Create(connectionString)) {
using (IDbCommand command = connection.CreateCommand()) {
command.CommandText = "CalcSelectDDSizeAndTilesPerBoxAll";
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 30;
connection.Open();
using (IDataReader r = command.ExecuteReader(CommandBehavior.CloseConnection)) {
while (r.Read()) {
DropDownOption option = new DropDownOption {
value = r["SizeAndNumInBox"].ToString(),
text = r["Descr"].ToString()
};
options.Add(option);
}
}
LastErrorMsg = string.Empty;
}
}
} catch (Exception ex) {
LastErrorMsg = ex.Message;
//consider logging error
options = new List<DropDownOption>();
}
return options;
}
}
请注意显式注入支持的ConnectionStrings
和IDbConnectionFactory
以及它们如何影响目标CalcSelectDDSizeAndTilesPerBoxAll
功能的实现。
因此,所有支持的抽象和实现都应在启动时注册
public void ConfigureServices(IServiceCollection services) {
services.Configure<CookiePolicyOptions>(options => {
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
//bind object model
ConnectionStrings connections = Configuration.Get<ConnectionStrings>();
//add it to the service collection so that is accessible for injection
services.AddSingleton(connections);
//register connection factory
services.AddSingleton<IDbConnectionFactory, SqlConnectionFactory>();
//register data provider
services.AddSingleton<IDataProvider, MyDataProvider>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
最后,控制器只能依赖于执行功能的实际需要,而不必充当使者并传递注入的成员
public class ServicesController : Controller {
private readonly IDataProvider myData;
public ServicesController(IDataProvider myData) {
this.myData = myData;
}
public IActionResult Index() {
return View();
}
// service returning json for dropdown options fill for tile calculator
public IActionResult GetCalcDDOptions() {
var calcOptions = myData.CalcSelectDDSizeAndTilesPerBoxAll();
return Ok(calcOptions);
}
}
答案 1 :(得分:0)
Startup.cs是VS2019(dotnetcore 2.2)中的默认模板,不需要任何更改。 在控制器中,我添加了几件事:
using Microsoft.Extensions.Configuration;
在控制器类中,我添加了:
private readonly IConfiguration configuration;
public ServicesController(IConfiguration config)
{
this.configuration = config;
}
我更改了模型类中的方法,以接受配置作为参数。 这是从控制器调用时的样子:
var calcOptions = MyData.CalcSelectDDSizeAndTilesPerBoxAll(this.configuration);
完整的控制器代码(供参考):
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using TestAppWithService.Models;
namespace TestAppWithService.Controllers
{
public class ServicesController : Controller
{
private readonly IConfiguration configuration;
public ServicesController(IConfiguration config)
{
this.configuration = config;
}
public IActionResult Index()
{
return View();
}
// service returning json for dropdown options fill for tile calculator
public IActionResult GetCalcDDOptions()
{
var calcOptions = MyData.CalcSelectDDSizeAndTilesPerBoxAll(this.configuration); //note: pass the config to the model
return new ObjectResult(calcOptions);
}
}
}
在模型中,我添加了:
using Microsoft.Extensions.Configuration;
然后在我添加了连接信息参数的方法中
public static List<DropDownOption> CalcSelectDDSizeAndTilesPerBoxAll(IConfiguration config)
在方法内部,获取数据库连接字符串很简单:
string dbconn = config.GetConnectionString("DefaultConnection");
该模型的完整代码:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Extensions.Configuration;
namespace TestAppWithService.Models
{
// This is for custom database functions for services
public class MyData
{
static string LastErrorMsg = string.Empty;
public static List<DropDownOption> CalcSelectDDSizeAndTilesPerBoxAll(IConfiguration config)
{
Boolean HasErrors = false;
var retval = new List<DropDownOption>();
string dbconn = config.GetConnectionString("DefaultConnection");
using (SqlConnection conn = new SqlConnection(dbconn))
{
using (SqlCommand cmd = new SqlCommand("CalcSelectDDSizeAndTilesPerBoxAll", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 30;
try
{
conn.Open();
using (SqlDataReader r = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (r.HasRows)
{
while (r.Read())
{
DropDownOption ddo = new DropDownOption();
ddo.value = r["SizeAndNumInBox"].ToString();
ddo.text = r["Descr"].ToString();
retval.Add(ddo);
}
}
}
LastErrorMsg = string.Empty;
}
catch (Exception ex)
{
LastErrorMsg = ex.Message;
HasErrors = true;
}
}
if (!HasErrors)
{
return retval;
}
else
{
return new List<DropDownOption>(); //just an empty list returned
}
}
}
}
}
关于踢球,这里是使用JavaScript(测试页)的视图,以使用该服务:
@{
ViewData["Title"] = "Test";
}
<script type="text/javascript">
$(function () {
$("#btnFillDD").click(function () {
RetrieveCalcOptionsDD();
});
function RetrieveCalcOptionsDD() {
var ddl = $("#TilesInCartonBySize");
var oldEvent = ddl.attr("onchange");
ddl.attr("onchange", ""); //remove change event
$.ajax({
url: '../Services/GetCalcDDOptions',
dataType: 'json',
method: 'get',
success: function (retdata) {
ddl.empty();
$.each(retdata, function () {
ddl.append($("<option></option>").val(this['value']).html(this['text']));
});
},
error: function (err) {
console.log('Error (RetrieveCalcOptionsDD): ' + JSON.stringify(err, null, 2));
}
});
ddl.attr("onchange", oldEvent); //add change event back
};
});
</script>
<h1>Test</h1>
<p><button id="btnFillDD">Click Me</button></p>
<p>
<select id="TilesInCartonBySize" class="calcText" onchange="calculate(this.form);">
</select>
</p>
请注意,此“服务”只是返回json的视图(因此您可以将其用于任何东西)。
一切都很好。