我是ASP.NET Core / C#的新手,并且正在努力学习 . 我已经阅读过教程,观看视频,甚至还买了一本书 . 我想把我的 AppDBcontext
注入我的模特..
这是我的 Startup
课程
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
string dbConnection = Configuration["ConnectionStrings:AzureSQL"];
services.AddDbContext<AppDbContext>(options => {
options.UseSqlServer(dbConnection);
});
services.AddScoped<AppDbContext>();
services.AddMvc();
}
和我的 AppDbContext.cs
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
public DbSet<Monthly> Monthly { get; set; }
public DbSet<Bill> Bill { get; set; }
}
我尝试过类似我模特的东西
public class Bill
{
public AppDbContext _ctx;
public Bill(AppDbContext db)
{
_ctx = db;
}
public class BillGetParams
{
public string MonthlyID { get; set; }
public string UserID { get; set; }
public string BillID { get; set; }
}
public int ID { get; set; }
public int? MonthlyID { get; set; }
public string BillName { get; set; }
public string Comment { get; set; }
public int? Amount { get; set; }
public bool? Payed { get; set; }
public bool? Recursive { get; set; }
public string UserID { get; set; }
public string UUID { get; set; }
public DateTime? CreatedAt { get; set; }
public static async Task<List<Bill>> LoadBills(BillGetParams billParams)
{
var bills = _ctx.Bill.FromSql($@"
SELECT * FROM bills WHERE MonthlyId={billParams.MonthlyID}");
return await bills.ToListAsync();
}
public static async Task<Bill> LoadBill(BillGetParams param)
{
var bill = _ctx.Bill.FromSql($@"
SELECT * FROM bills
WHERE UserID='{param.UserID}' AND ID='{param.BillID}'
");
return await bill.SingleOrDefaultAsync();
}
编辑:添加 Bill
类的部分代码和使用 _ctx
的方法,也通过删除 static
和private-> public更新构造函数;
我收到一个错误:
System.NullReferenceException:未将对象引用设置为对象的实例 .
因为似乎 db
的分配从未发生过......
我不确定哪个最好,但我之前使用的是 AppDbContext
. 我应该像这样继续使用吗?
using(var ctx = new AppDbContext())
{
var bills = ctx.Bill.FromSql($@"select 1 from bills")
// do stuff
}
从互联网上的例子来看,DI在控制器上运行良好..但是我不想从控制器那里做SQL的东西..有没有更好的方法在 dotnet
中抽象SQL /数据访问?或者我做错了?
solution1: 所以阅读,试用,@Bharat的解决方案和实验 . 我用最简单的方式解决了我的问题..希望我是对的 . 我在 BillController
中添加了这个使用 Bill.LoadBill()
我现在可以很好地访问我的SQL了 .
private Bill _bill;
public BillController(AppDbContext db)
{
_bill = new Bill(db);
}
谢谢!
2 回答
System.NullReferenceException
你得到
System.NullReferenceException: Object reference not set to an instance of an object.
的原因是你的构造函数方法是private
:Solution: 您的构造函数应为
public
.否则它不能在它自己的课程之外访问 . 你可以通过在
_ctx = db
上放置一个断点来测试它,你会发现它没有被调用 .为了进一步阅读和理解,我建议您阅读此Microsoft文档:Dependency Injection in ASP.NET Core
我看到的最大的错误就是这个:
请求改变
我认为提供模型的方法可以直接访问它们的实例,但请不要这样做,即使它是要填充额外的属性或列表 .
这样您就可以在整个应用程序中拆分DataAccess代码(sql) . 相反,最好将所有dataAcces分组到控制器中,甚至在单独的项目和服务中更好 .
服务的优点是:
您可以通过IOC容器解决它
没有奇怪的模型构造函数的问题(现在每个模型都需要AppDbContext,即使它不需要它)
如果服务实现了相同的接口,您可以轻松地将服务替换为另一个服务 . (你使用这个界面的课程)
虚拟实例方法不可覆盖静态方法 . (当项目变大时会导致问题)
这将导致以下代码: