C#日常小问题记录

8 篇文章 0 订阅

1、禁止对象序列化时的循环引用
如果正在使用 ASP.NET Core,则可以将 Json.NET 配置为忽略在对象图中找到的循环引用。 此配置是通过 Startup.cs 中的 ConfigureServices(…) 方法完成的。

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddMvc()
        .AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );
    ...
}

另一种方法是使用 [JsonIgnore] 特性修饰其中一个导航属性,该特性指示 Json.NET 在序列化时不遍历该导航属性。
https://docs.microsoft.com/zh-cn/ef/core/querying/related-data/serialization

2、sql server判断临时表是否存在

 IF OBJECT_ID('tempdb.dbo.#tempemployees','U') IS NOT NULL DROP TABLE dbo.#tempemployees;

3、编译Ext页面的方法
1)编译软件:sencha
2)编译步骤:
a、通过cmd跳转到UI文件夹
b、执行编译命令:sencha app build

4、mvc 4设置主页的方式
1)在web.config中设置

<defaultDocument>
	<files>
		<clear />
        <add value="index.html" />
	</files>
</defaultDocument>

2)在HomeController中设置

public class HomeController : Controller
{
	public ActionResult Index()
	{
		return Redirect("ui/index.html");
    }        
}

5、EF Core使用程序包控制台进行数据库的升级与迁移
1)如何打开命令行:vs studio–>工具–>NuGet包管理器–>程序包管理器控制台
2)创建实体类
3)创建实体类配置类

namespace AbpVueTest.EntityFrameworkCore {
    class TestEntityConfiguration : IEntityTypeConfiguration<TestEntity> {
        public void Configure(EntityTypeBuilder<TestEntity> builder) {
            builder.Property(p => p.Age).HasColumnType("int");
        }
    }

4)创建DbContext

namespace AbpVueTest.EntityFrameworkCore {
    public class TestEntityDbContext : AbpDbContext {
        public TestEntityDbContext(DbContextOptions<TestEntityDbContext> options) : base(options) {

        }
        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            #region 注册领域模型与数据库的映射关系
           modelBuilder.ApplyConfiguration(new TestEntityConfiguration());
            
            #endregion
            base.OnModelCreating(modelBuilder);
        }

    }
}

5)CodeFirst映射实体类与数据库字段的类型

namespace AbpVueTest.EntityFrameworkCore {
    class TestEntityConfiguration : IEntityTypeConfiguration<TestEntity> {
        public void Configure(EntityTypeBuilder<TestEntity> builder) {
            builder.Property(p => p.Age).HasColumnType("int");
        }
    }
  1. 创建实体类DbContextFactory,配置数据库连接
namespace AbpVueTest.EntityFrameworkCore {
    class TestEntityDbContextFactory : IDesignTimeDbContextFactory<TestEntityDbContext> {
        TestEntityDbContext IDesignTimeDbContextFactory<TestEntityDbContext>.CreateDbContext(string[] args) {
            var builder = new DbContextOptionsBuilder<TestEntityDbContext>();
            builder.UseSqlServer("Server=10.0.X.X; Database=XXX;User ID=XXX;Password=XXXX; Trusted_Connection=false;");
            return new TestEntityDbContext(builder.Options);
        }
    }
}

7)命令行执行
7.1) add-migration ModifySupplyPlanDailyInfo -context “AbpVueTest.EntityFramework.TestEntityDbContext”
7.2)update-database -context “AbpVueTest.EntityFrameworkCore.TestEntityDbContext”
6、Vuex state分模块
1)创建Module
Vuex 分模块
2)引入模块
引入模块
3)使用模块
页面中使用模块
7、Apb GetAll实现过滤查询
在CRUDService中的GetAll方法会调用CreateFilteredQuery方法,对返回的结果进行过滤

protected override IQueryable<SupplyPlanDailyConfigInfo> CreateFilteredQuery(PagedSupplyPlanDailyConfigResultRequestDto input)
        {
            return Repository.GetAll().WhereIf(!input.Company.IsNullOrWhiteSpace(),x=>x.Company==input.Company)
               .WhereIf(!input.SubCon.IsNullOrWhiteSpace(),x=>x.SubCon==input.SubCon)
               .WhereIf(!input.DeliveryLocation.IsNullOrWhiteSpace(),x=>x.DeliveryLocation==input.DeliveryLocation);
        }

8、Sql Server 查询条件区分大小写
添加collate Chinese_PRC_CS_AS_WS可使得查询条件区分大小写,ac和AC不匹配,如果不加则ac和Ac,AC等都匹配

select * from T_MD_Product_SrCtl WHERE description collate Chinese_PRC_CS_AS_WS ='AC'

9、C#中的异步理解

Using await allows your application or service to perform useful work while a task is running by yielding control to its caller until the task is done. Your code does not need to rely on callbacks or events to continue execution after the task has been completed. The language and task API integration does that for you. If you’re using Task<T>, the await keyword will additionally “unwrap” the value returned when the Task is complete. The details of how this works are explained further below.

这段话表明,使用await关键字后,在我们的代码中不再需要回调函数或事件机制来监听异步事件的完成,然后处理事件完成之后需要进行的工作。但这并不意味着不需要使用回调函数或者事件机制来监听事件的完成,并执行后续的工作。只不过是这些工作由编程语言和task的api来帮我们完成了,不需要我们在自己的代码中添加这部分的代码了而已。

10、ASP.NET Core依赖注入报错
向单例实例中注入Scoped实例(Cannot consume scoped service xxx from singleton yyy)

ASP.NET core built in dependency injection container is protecting you against a dependency injection anti pattern called “captive dependencies” (you can read more about it and dependency injection in general here).
The basic idea is that a class having a certain lifetime can only depend on objects having a lifetime equal to or longer than its own lifetime. This is because when you do dependency injection you provide a class with all its dependencies (usually via constructor injection) and that class save a reference to the dependency, so that it will be able to use it later when it needs.
Because the class you are designing saves a reference to the injected object, then the injected object is kept alive (at least) for as long as your class’ instance it’s alive. Maybe an example could help you to understand.

11、ASP.NET Core注册Singleton与Scoped的DBContext

//注册仓储
            //services.AddSingleton(options => {
            //    var builder = new DbContextOptionsBuilder<LogCenterReaderDbContext>();
            //    var op = builder.UseSqlServer(Configuration.GetSection("ConnectionStrings:LogCenterReaderContext").Value).Options;
            //    return new LogCenterReaderDbContext(op);
            //});
            services.AddDbContext<LogCenterReaderDbContext>(options=> {
                options.UseSqlServer(Configuration.GetSection("ConnectionStrings:LogCenterReaderContext").Value);
            });
            services.AddDbContext<LogCenterWritterDbContext>(options => {
                options.UseSqlServer(Configuration.GetSection("ConnectionStrings:LogCenterWritterContext").Value);
            });

12、ASP.NET Core 返回类型
01
02
13、文件下载
ajax请求会自动解析返回的数据,所以不会对文件进行下载,因此需要以表单的方式向后端请求数据

 onVaildateButtonClick: function () {
        var vcObj = this.getView().lookupReference('validateCode');
        if (!vcObj.isValid()) {
            //取件码格式有误,不再继续验证
            return;
        }

        //检查验证码是否正确
        //1、获取验证
        var vc = this.getView().lookupReference('validateCode').value;
        //2、获取验证消息提示框
        var vcTip = this.getView().lookupReference('validateResultTip');
        //3、获取验证窗口
        var validateWin = this.getView();
        //4、请求后端验证取件码
        Ext.Ajax.request({
            url: 'api/v1/fileDownload/GetFileDownloadUrl',
            params: { 'vc':vc,'file':'file'},
            method: 'GET',
            success: function (response, options) {
                var fileUrl = response.responseText;
                if (fileUrl == "") {
                    //取件码验证失败
                    //1、验证字段(该验证器验证结果为false)
                    vcObj.validator = function () { return "验证码有误!" };
                    vcObj.isValid();
                    //2、显示验证结果提示
                    vcTip.setHidden(false);
                } else {
                    //验证成功开始下载文件
                    //直接通过Ext.Ajax.request请求下载不能实现下载,ajax会自动解析文件内容,而不会下载,所以这里使用表单
                    var form = Ext.create('Ext.form.Panel', {
                        standardSubmit: true,
                        url: "api/v1/fileDownload/DownloadFile",
                        method: 'GET',
                        target: '_blank', // Avoids leaving the page. 
                        params: { "fileUrl": fileUrl }
                    });
                    form.submit()
                   //表单提交后关闭form与验证窗口
                    Ext.defer(function () {
                        form.close();
                        validateWin.close();
                    }, 100);
                }
            },
            failure: function (response, options) {
                Ext.MessageBox.alert('失败', '请求超时或网络故障,错误编号:' + response.status);
            }
        });

后端:
小文件下载:可以把整个文件全部读入内存内后一次性写出

/// <summary>
        /// 小文件下载:先将文件全部读入内存中,然后写出
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> DownloadFileDirect() {
            //web根路径
            //string filePath = _hostEnvrionment.WebRootPath;
            HttpResponseMessage respMsg = new HttpResponseMessage();
            respMsg.StatusCode = HttpStatusCode.OK;
            //项目根路径
            string rootPath = _hostEnvrionment.ContentRootPath;
            string filePath = rootPath + "/appsettings.json";
            FileStream fs = System.IO.File.OpenRead(filePath);
            //将整个文件读入内存中
            var memory = new MemoryStream();
            await fs.CopyToAsync(memory);
            memory.Position = 0;
            //以二进制流写出文件
            return File(memory, "application/octet-stream",Path.GetFileName(filePath)); 
        }

大文件下载:在以前的版本中可以使用HttpContext.Current.Response进行文件按的下载,而在Asp.Net Core中需要使用Response.Body.Write(buffer, 0, currentRead)

public IActionResult LargeFileDownload()
        {
            string rootPath = _hostEnvrionment.ContentRootPath;
            string filePath = rootPath + "/appsettings.json";
            var fileName = Path.GetFileName(filePath);//测试文档
            int bufferSize = 2048;//这就是ASP.NET Core循环读取下载文件的缓存大小,这里我们设置为了1024字节,也就是说ASP.NET Core每次会从下载文件中读取1024字节的内容到服务器内存中,然后发送到客户端浏览器,这样避免了一次将整个下载文件都加载到服务器内存中,导致服务器崩溃
            Response.ContentType = "application/otect-stream";//由于我们下载的是一个Excel文件,所以设置ContentType为application/vnd.ms-excel
            var contentDisposition = "attachment;" + "filename=" + HttpUtility.UrlEncode(fileName);//在Response的Header中设置下载文件的文件名,这样客户端浏览器才能正确显示下载的文件名,注意这里要用HttpUtility.UrlEncode编码文件名,否则有些浏览器可能会显示乱码文件名
            Response.Headers.Add("Content-Disposition", new string[] { contentDisposition });
            
            //使用FileStream开始循环读取要下载文件的内容
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                using (Response.Body)//调用Response.Body.Dispose()并不会关闭客户端浏览器到ASP.NET Core服务器的连接,之后还可以继续往Response.Body中写入数据
                {
                    long contentLength = fs.Length;//获取下载文件的大小
                    Response.ContentLength = contentLength;//在Response的Header中设置下载文件的大小,这样客户端浏览器才能正确显示下载的进度
                    byte[] buffer;
                    long hasRead = 0;//变量hasRead用于记录已经发送了多少字节的数据到客户端浏览器
                    
                    //如果hasRead小于contentLength,说明下载文件还没读取完毕,继续循环读取下载文件的内容,并发送到客户端浏览器
                    while (hasRead < contentLength)
                    {
                        //HttpContext.RequestAborted.IsCancellationRequested可用于检测客户端浏览器和ASP.NET Core服务器之间的连接状态,如果HttpContext.RequestAborted.IsCancellationRequested返回true,说明客户端浏览器中断了连接
                        if (HttpContext.RequestAborted.IsCancellationRequested)
                        {
                            //如果客户端浏览器中断了到ASP.NET Core服务器的连接,这里应该立刻break,取消下载文件的读取和发送,避免服务器耗费资源
                            break;
                        }
                        buffer = new byte[bufferSize];
                        int currentRead = fs.Read(buffer, 0, bufferSize);//从下载文件中读取bufferSize(1024字节)大小的内容到服务器内存中
                        Response.Body.Write(buffer, 0, currentRead);//发送读取的内容数据到客户端浏览器
                        hasRead += currentRead;//更新已经发送到客户端浏览器的字节数
                    }
                    Response.Body.Flush();//调用Flush方法,释放服务器内存空间
                }
            }
            return new EmptyResult();
        }

14、EF分页查询与EF连接查询

var task = _fileTransTaskRepository.FileTransConext.Set<FileTransTaskVO>();
            var net = _fileTransTaskRepository.FileTransConext.Set<TransNasVO>();
            var res = (from t in task
                       join n in net
                       on t.TargetNasID equals n.ID
                       select new { 
                        targetNetID = t.TargetNasID,
                        netID = n.ID,
                        targetPath = t.TargetNasPath
                       }).Take(5).ToArray();
            var leftJoinRes = (from t in task
                       join n in net
                       on t.TargetNasID equals n.ID into leftJoinTemp
                       from record in leftJoinTemp.DefaultIfEmpty()
                               select new
                       {
                           targetNetID = t.TargetNasID,
                           netID = record.ID,
                           root = record.Root,
                           targetPath = t.TargetNasPath
                       }).Take(5).ToArray();

15、EF查询表达式构建

public static class PredicateBuilder
	{
		public static Expression<Func<T, bool>> True<T>() { return f => true; }
		public static Expression<Func<T, bool>> False<T>() { return f => false; }

		public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
												  Expression<Func<T, bool>> expr2)
		{
			var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
			return Expression.Lambda<Func<T, bool>>
				 (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
		}

		public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
												   Expression<Func<T, bool>> expr2)
		{
			var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
			return Expression.Lambda<Func<T, bool>>
				 (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
		}
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值