我想将我当前的 DbContext 添加到我使用的任何类中,目前我只是将 _context 传递给公共变量。
在此控制器示例中,每次我想要创建项目时,我都会传递 _context
[HttpPost("receta/{id}")]
[APIauth("medico")]
public IActionResult PostItemsReceta(int id, [FromBody]Data[] items) {
var tran = _context.Database.BeginTransaction(); //DBB transaction begins
try {
foreach (Data item in items)
new Item(id, item, _context); //I pass the _context like this.
tran.Commit();
return Ok();
} catch (Exception e) {
tran.Rollback();
return BadRequest("Not inserted!!");
}
}
在班级项目中我有这个
public class Item
{
[Key]
public int id { get; set; }
public DateTime? fcaducidad { get; set; }
public string nombre { get; set; }
public Int32 diagnostico { get; set; }
public Item() { }
public Item (int receta, Data i, MyDbContext _context) {
try {
var q = $"EXEC ItemReceta_Insert @idItemFarmacia={i.itemFarmacia.id}" +
$", @idDiagnostico={i.diagnostico}, @cantidad={i.cantidad}" +
$", @receta={receta}, @posologia='{i.posologia}'";
_context.Database.ExecuteSqlCommand(q);
} catch (Exception e) {
throw new Exception("Error al insertar ItemReceta", e);
}
}
public static Item[] Report( int receta, MyDbContext _context)
{
string q = $"EXEC Item_Report @receta={receta}";
return _context.Item.FromSql(q).ToArray();
}
}
我不想直接访问控制器中的上下文,因为我多次使用它,我想要
new Item(id, item);
不
new Item(id, item, _context);
Item.Report(bla, _context);
new WhatEverClass(name, age, _context);
答案 0 :(得分:6)
我认为你并没有真正区分你的顾虑,有很多方法可以做到这一点,但是我会提出一种非常简单的方法来将事情注入你自己的课程中(I&#39 ; ll会遗漏解决方案中的一些属性以保持简单)。您需要做的主要事情是将您的课程注册为服务。所以..
首先,让你的物品成为POCO
public class Item
{
public int Id { get; set; }
}
现在将您的代码与您尝试将项目放入和放出数据库的方式相关联,使构造函数获取您的DbContext以便它将被注入
public class ItemService
{
private readonly ApplicationContext _context;
public ItemService(ApplicationContext context)
{
_context = context;
}
public void Add(Item item)
{
// A paramatized query of some sort to prevent sql injection
// see https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/advanced
var parameters = new List<object>();
_context.Database.ExecuteSqlCommand("", parameters);
}
}
现在,在您配置服务的地方添加您的项目服务
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationContext>();
services.AddScoped<ItemService>();
}
现在在你的控制器构造函数中说你想要服务,
private readonly ItemService _itemService
public MyFancyPantsController(ItemService itemService)
{
_itemService = itemService;
}
现在您可以在帖子上访问该服务
[Route("post")]
[HttpPost()]
public IActionResult PostItem()
{
// construct / deserialize items, then add them...
_itemService.Add(new Item());
return Ok();
}
现在......你可能会发现你有很多实体(比如Item)并且为它们创建服务都是PITA,所以你可能想要更通用的Repository服务。
答案 1 :(得分:0)
只需在构造函数中使用using (var db = new DbContext()) { ... }
。
这将完全奏效:
public class AppDbContext : DbContext
{
public DbSet<Item> Items { get; set; }
}
public class Data
{
public int Id { get; set; }
public string Value { get; set; }
}
public class Item
{
public Item()
{
}
public Item(IEnumerable<Data> data)
{
Data = data.ToList();
using (var db = new AppDbContext())
{
db.Items.Add(this);
db.SaveChanges();
}
}
public override string ToString()
{
return Data != null ? $"Item:{Id}, Data:{string.Join(',', Data.Select(i => i.Value))}" : $"Item:{Id}, Data:None";
}
public int Id { get; set; }
public ICollection<Data> Data { get; set; }
}
...
var i1 = new Item(new[] {new Data {Value = "1"}, new Data {Value = "2"}});
var i2 = new Item(new[] {new Data {Value = "3"}, new Data {Value = "4"}});
using (var db = new AppDbContext())
{
db.Items.Include(i => i.Data).ToList().ForEach(Console.WriteLine);
}
有很多理由说明这是一个坏主意(无法创建持久化项目,无论如何都需要默认构造函数,不能轻松执行批量插入,高耦合,无法测试),但它似乎是我的解决方案这正是你的解决方案,所以我不确定这是否有帮助?
值得注意的是,由于连接池,使用以下内容创建 new DbContext
会更好,更高效。
using (var db = new AppDbContext())
{
...
}
比手动或使用DI传递一个单例对象;这是因为上下文在内部缓存查询结果,如果您将其用作单例,则基本上存在缓慢的内存泄漏。
即。这个:public Item (int receta, Data i, MyDbContext _context)
实际上比几个using (var db = new AppDbContext() { ... }
明显更糟,除非您专门使用结果缓存。