C# 将DbContext添加到所有类,而不仅仅是.NETCore中的控制器
我想将我当前的DbContext添加到我使用的任何类中,目前我只是像传递普通变量一样传递\u context 在这个控制器示例中,每当我想要创建一个项目时,我都会传递\u上下文C# 将DbContext添加到所有类,而不仅仅是.NETCore中的控制器,c#,entity-framework,asp.net-core,.net-core,dbcontext,C#,Entity Framework,Asp.net Core,.net Core,Dbcontext,我想将我当前的DbContext添加到我使用的任何类中,目前我只是像传递普通变量一样传递\u context 在这个控制器示例中,每当我想要创建一个项目时,我都会传递\u上下文 [HttpPost("receta/{id}")] [APIauth("medico")] public IActionResult PostItemsReceta(int id, [FromBody]Data[] items) { var tran = _context.Database.BeginTransa
[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);
不是
我认为您并没有真正地分离您的关注点,有很多方法可以做到这一点,但是我将提供一种非常简单的方法来将内容注入到您自己的类中(为了保持简单,我将省略解决方案中的一些属性)。您需要做的主要事情是将类注册为服务。所以 首先,把你的物品做成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);
}
}
现在,在您的帖子上,您可以访问该服务
[Route("post")]
[HttpPost()]
public IActionResult PostItem()
{
// construct / deserialize items, then add them...
_itemService.Add(new Item());
return Ok();
}
现在……您可能会发现您有很多实体(比如Item),为它们创建服务是一个PITA,所以您可能需要更通用的存储库服务 只需在构造函数中使用(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; }
}
这是一个坏主意的原因有很多(无法创建具有持久性的项,无论如何都需要ef的默认构造函数,无法轻松执行大容量插入,高耦合,不可能测试),但似乎我的解决方案正是您的解决方案,所以我不确定这是否有帮助
值得注意的是,由于连接池的存在,创建一个新的DbContext
会更好,性能也会更好:
using (var db = new AppDbContext())
{
...
}
而不是手动或使用DI传递一个单例对象;这是因为上下文在内部缓存查询结果,如果将其作为单例使用,基本上会出现缓慢的内存泄漏
例如:
公共项(int receta,Data i,MyDbContext{u context)
实际上比使用(var db=new AppDbContext(){…}的几个要糟糕得多,除非您专门使用结果缓存。您是否在程序的Startup.cs中添加了MyDbContext?我的意思是{u services.AddDbContext(…):在ConfigureServices中..任何恶意使用都可能对您的数据库做任何他们想做的事(至少)。使用依赖项注入?然后实现CQR、存储库模式或您喜欢的任何方式…是@Steve,我在启动时添加了MyBbContext,我在控制器中使用它。var db=new AppDbContext()将不工作,因为AppDbContext没有默认构造函数。
[Route("post")]
[HttpPost()]
public IActionResult PostItem()
{
// construct / deserialize items, then add them...
_itemService.Add(new Item());
return Ok();
}
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);
}
using (var db = new AppDbContext())
{
...
}