C# 将DbContext添加到所有类,而不仅仅是.NETCore中的控制器

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

我想将我当前的DbContext添加到我使用的任何类中,目前我只是像传递普通变量一样传递\u context

在这个控制器示例中,每当我想要创建一个项目时,我都会传递\u上下文

[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())
{
    ...
}