首页 > 数据库 >C# abp中EfCore执行原生sql和事务操作

C# abp中EfCore执行原生sql和事务操作

时间:2023-04-26 17:57:38浏览次数:41  
标签:C# serviceProvider dbContext abp dbContextProvider EfCore var async logger

ef自带的方法是没有执行原生sql的,必须在仓储实现类中注入dbContextProvider、然后就可以使用FromSqlRaw查询,ExecuteSqlRawAsync执行新增、修改、删除,efcore方法都是自带事务的,有时候我们想在自己的业务逻辑中嵌入事务,就使用CreateExecutionStrategy创建事务操作:

public class AccessRecordRepository : EfCoreRepository<TestDbContext, AccessRecord, Guid>, IAccessRecordRepository
    {
        private readonly ILogger<AccessRecordRepository> _logger;
        private readonly IDbContextProvider<TestDbContext> _dbContextProvider;
        public AccessRecordRepository(IDbContextProvider<TestDbContext> dbContextProvider, ILogger<AccessRecordRepository> logger) : base(dbContextProvider)
        {
            _logger = logger;
            _dbContextProvider = dbContextProvider;
        }

        /// <summary>
        /// join关联查询
        /// </summary>
        /// <returns></returns>
        public async Task GetList()
        {
            string ZLZT = "状态";
            try
            {
                var dbContext = _dbContextProvider.GetDbContext();  // 建议不要调用using (var dbContext = _dbContextProvider.GetDbContext())释放,如果后面有调用GetQueryableAsync,会出现链接被释放错误

                var list = dbContext.DataDictionaryItems.FromSqlRaw("select A.ZidianLBID, A.Bianma, A.Mingcheng  from dataDictionaryitem A " +
                    "join dataDictionary B ON A.ZidianLBID = B.Id " +
                    $"where ZidianLBMC = '{ZLZT}'") // ef已经考虑了sql注入,因此不需要new MySqlParameter("@ZLZT", "状态"),注意字符值必须添加 ''
                    .Select(w => new TDataDto { Bianma = w.Bianma, Mingcheng = w.Mingcheng, ZidianLBID = w.ZidianLBID }) // 定义新类接受join查询结果,不然只能select *  ; TDataDto必须添加属性 [Serializable]
                    .ToList();

                _logger.LogInformation($"查询字典结果:{JsonConvert.SerializeObject(list)}");
            }
            catch (Exception ex) 
            {
                _logger.LogInformation($"查询字典异常: {ex}");
            }
         }

        /// <summary>
        /// 执行SQL
        /// </summary>
        /// <returns></returns>
        [Obsolete]
        public async Task RemoveAllAsync()
        {
            _logger.LogInformation($"RemoveAllAsync start");
            using (var dbContext = _dbContextProvider.GetDbContext())
            {
                try
                {
                    int result = await dbContext.Database.ExecuteSqlRawAsync("TRUNCATE TABLE access_record"); 
                    _logger.LogInformation($"RemoveAllAsync result = {result}"); // TRUNCATE成功影响行数0
                }
                catch (Exception ex)
                {
                    _logger.LogError($"RemoveAllAsync exception: {ex}");
                }
            }
        }

        /// <summary>
        /// 执行事务
        /// </summary>
        /// <returns></returns>
       private async Task TestTran()
        {
            using (var dbContext = _dbContextProvider.GetDbContext())
            {
                var strategy = dbContext.Database.CreateExecutionStrategy();
                await strategy.ExecuteAsync(async() => 
                {
                    using (var tran = dbContext.Database.BeginTransaction())
                    {
                        try
                        {
                            var result = await dbContext.AccessRecord.AddAsync(new AccessRecord { });
                            await dbContext.SaveChangesAsync();
	            	    tran.Commit();
                        }
                        catch (Exception ex)
                        {
                            tran.Rollback();
                        }
                    }
                });
            }
        }

	  /// <summary>
        /// 根据条件删除
        /// </summary>
        /// <returns></returns>
	  public async Task<List<MyEntity>> RemoveEntitiesAsync(string name)
	  {
    		using (var dbContext = _dbContextProvider.GetDbContext())
    		{
        		var entities = await dbContext.Set<MyEntity>()
            	    .Where(e => e.Name.Contains(name))
            	    .ToListAsync();

			// 也可以修改状态删除
			// foreach (var entity in entities)
        		// {
            	     //   dbContext.Entry(entity).State = EntityState.Deleted;
        		// }

			dbContext.RemoveRange(entities);
        		await dbContext.SaveChangesAsync();

        		return entities;
    		}
	  }
    }

另外说一个常见的错误:Cannot access a disposed context instance , 特别是在你写一些定时器、TCP服务,继承BackgroudService方法中,很容易出现,网上说在方法上面加[UnitOfWork]无效,也有人说仓储实现类继承ITransientDependency,仓储默认使用IScopeDependency,这个也无效,最终只有2个方案:

1、仓储操作的方法都改成同步的

2、使用IServiceProvider获取仓储

private readonly IServiceProvider _serviceProvider;

public AccessRecord(IHost host)
{
    _serviceProvider = host.Services;
}

public async Task GetList()
{
    using var serviceProvider = _serviceProvider.CreateScope();
    var _accessRecordRepository  = serviceProvider.ServiceProvider.GetRequiredService<IAccessRecordRepository>

   // 类似的,获取ObjectMapper对象,也需要使用IServiceProvider
   // _= Task.Run(async () =>
   // {
   //    using var serviceProvider = _serviceProvider.CreateScope();
   //    var _objectMapper = serviceProvider.ServiceProvider.GetRequiredService<IObjectMapper>
   // }).ContinueWith(async t => { await CallBackActionAsync(keyid, items); });

  }

  

标签:C#,serviceProvider,dbContext,abp,dbContextProvider,EfCore,var,async,logger
From: https://www.cnblogs.com/fanyang1/p/17356842.html

相关文章

  • java连接jdbc-mssql数据库
    packagecom.swift.erp;importjava.sql.SQLException;importjava.sql.Statement;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;publicclassAPP{//引入sqljdbc.jarpublicstaticvoidmain(String[]args......
  • detach,主线程终止后子线程会结束吗
    transfrom:https://blog.csdn.net/a0408152/article/details/129093394此前,我对detach的理解是,当主线程退出后,子线程能够继续存在。实际上,当主线程退出后,子线程也随之结束了。先看一个例子:#include<iostream>#include<thread>#include<unistd.h>usingnamespacestd;in......
  • markdown教程(Mac版)—测试文档
    markdown的使用说明(Mac)——测试文档这是借鉴哔哩哔哩的up主,维素s的视频内容。这个版本主要是测试vscode编写博客园。侵权删。网址:https://www.bilibili.com/video/BV1h84y1Y7nn/?spm_id_from=333.337.search-card.all.click&vd_source=9b34f68ae41432066bc35c80468eef98一、标......
  • c++11/14线程池
    c++11//#pragmaonce#include<iostream>#include<thread>#include<memory>#include<vector>#include<queue>#include<functional>//std:;function#include<future>//std::pac......
  • jdk20 Structured Concurrency 结构化并发官网示例
    此特性还在孵化,后续版本可能有变动//全部执行直到有失败的任务Stringhandle()throwsExecutionException,InterruptedException{try(varscope=newStructuredTaskScope.ShutdownOnFailure()){Future<String>user=scope.fork(()->"")......
  • Centos7部署docker
     一.安装前可以先开放443端口 firewall-cmd--zone=public--add-port=443/tcp--permanent1.正常使用yum安装yuminstall-ydocker-ce如果在过程中出现失败,解决办法1.yumcleanall2.yummakecache3.重新安装如果出现Couldn‘topenfile/mnt/repodata/repomd.x......
  • 关于idea使用Tomcat打开jsp文件页面失败的问题的解决
    问题描述在idea里面使用Tomcat打开jsp文件频繁报错,检查相关路径也没有任何问题,而且用来测试的jsp文件还是最简单的形式,困扰了大概5分钟左右问题解决经过查询百度可知,这次不是路径的问题,而是需要将我们在web文件夹里面创建的jsp文件复制到target文件夹里面保持与target文件夹里......
  • java excel带图片导入
    日常项目中使用easyExcel但是easyExcel不支持带图片的excel导入,后面通过网络查找,再加上询问技术经理终于解决,大前提是图片在excel中不是嵌入的,需要悬浮才可以读取。代码如下引用jar包为<!--需要2.10版本及以上不然excel缺少工具类--><dependency><groupId>com......
  • 设计模式(18)-Command Pattern
    一、 命令(Command)模式命令(Command)模式属于对象的行为模式【GOF95】。命令模式又称为行动(Action)模式或交易(Transaction)模式。命令模式把一个请求或者操作封装到一个对象中。命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。......
  • H3C S5560S 修改VLAN Address
    <SW1>sysSystemView:returntoUserViewwithCtrl+Z.[SW1]discu#version7.1.070,Release6126P20#sysnameSW1#interfaceVlan-interface1ipaddress192.168.3.51255.255.255.0<SW1>undo ipaddress192.168.3.51#Restorethedefaultsetting......