标签 C# 下的文章

Mongodb Driver for C#/.Net的增删改查

我之前在《.Net Core系列教程(三)——使用Mongodb》中,说过在.Net Core下,怎样使用Mongodb数据库,这篇文章就作为它的延伸,来说下在.Net中,怎样使用Mongodb Driver来进行最常用的增、删、改、查操作。当然,我这个的环境是在.Net Core下,在其他版本的.Net环境下,相差不大。我这实例中使用的驱动是2.4.0版的,而现在最新版本是2.4.4。
闲言少叙,还是撸代码吧。
先按《.Net Core系列教程(三)——使用Mongodb》文章中的方法,设置好数据库的相关配置,之后取得数据库:

    var db = client.GetDatabase("database");

这个代码可以按照自己的实际需求来写,比如这样:

    var db = client.GetDatabase(MongoUrl.Create(settings.Value.MongodbConnection).DatabaseName);

取得一个collection,这里以news表为例,Models.News是News的实例类:

    var collection = db.GetCollection<Models.News>("news");

我们再准备一下具体要操作的数据:

    var request=new Models.News(){title:"新闻测试",body:"这里是新闻测试的内容",author:"张三","status":True};

这些前提准备好了之后,再开始具体的数据库操作了

1.增加操作:

    collection.InsertOne(request);

2.修改操作:

    var query = new BsonDocument("_id", new ObjectId(id));
    var dict = new Dictionary<string, object> {
        { "title",request.title},
        { "body",request.body},
        { "author",request.author},
        { "status",request.status}
    };
    var data = new BsonDocument(dict);
    collection.UpdateOne(query, new BsonDocument("$set", data));

3.查询操作:

    //查列表
    int page=1;  //当前页号
    int pagesize=50;  //每页50条记录
    BsonDocument query = new BsonDocument(){"author":"张三","status":True};
    int total = Convert.ToInt32(collection.Count(query));  //数据总记录数
    var list = collection.Find(query).Sort(new BsonDocument("_id", -1)).Limit(pagesize).Skip((page-1)*pagesize).ToList();  //带分页查询,按_id倒序排序
    
    //查单条
    BsonDocument query = new BsonDocument("_id", _id);
    var data = collection.Find(query).FirstOrDefault();

4.删除操作:

    ObjectId _id = new ObjectId(id);
    collection.DeleteOne(new BsonDocument("_id", _id));

以上只是其中几个比较简单的用法,其实还有很多实现方法,比如异步方法、插入多条等等,其他的等有时间再整理吧。

.Net网站下使用Oracle数据库的环境设置

在.Net网站下使用Oracle,需要网站服务器安装Oracle数据库的客户端,这是目前必须要安装的。
以下是在Windows Server 2008 R2服务器环境下的设置方法及注意事项,其他系统可能会略有不同。
1.服务器需要安装Oracle数据库的客户端,版本为Oracle Database 11g Release 1,而且只能使用这个版本,其他版本不可行,另外需要与你的网站应用池的位数(32位或64位)一致;
2.安装时,安装类型选择“运行时”;
3.安装完成后,查看环境变量中,有没有把安装目录下的BIN文件夹添加到环境变量中,如:D:\app\Administrator\product\11.2.0\client_1\bin;;
4.打开安装目录右键属性,切换到“安全”选项卡,编辑,选中“Authenticated Users“,把”读取和执行“权限去掉,之后再重新勾选,之后”应用“;
5.最后一步,也是重要的一步,那就是重启服务器,不重启服务器不会生效。

这就可以了。

使用iText5来处理PDF

项目要求,通过pdf模板,把用户提交的数据保存到一个PDF文件中。其中有文字内容,也有图片。之前选了aspose.pdf,因为抠门,不能花钱买,就从网上找的的开心版,好不容易出来点模板,结果插入图片的时候,同一页只能插入一张图片,而官方的试用版是可以正常两张的,另外字段比较多,速度比较慢,几百个字段需要一分多钟,效率很低,放弃。之后尝试iText,发现要比aspose.pdf好用的多,下面就说下用法。
需要通过nuget安装iTextSharp,选第一个,版本号是5.5.12,也就是iText5版本,该版本是AGPL许可。
完整代码如下:

using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;

namespace Tools
{
    public class iTextPdf
    {
        Document pdfDocument = new Document();
        private string _path = "";

        #region 内容属性
        /// <summary>
        /// 文字
        /// </summary>
        public string Content { get; set; }

        /// <summary>
        /// X坐标
        /// </summary>
        public float X { get; set; }

        /// <summary>
        /// Y坐标
        /// </summary>
        public float Y { get; set; }

        /// <summary>
        /// 页索引(从0开始)
        /// </summary>
        public int PageIndex { get; set; }

        /// <summary>
        /// 类型
        /// 1-文字
        /// 2-勾选(图片)
        /// 3-签名
        /// 4-身份证正面
        /// 5-身份证反而
        /// </summary>
        public int Type { get; set; }

        /// <summary>
        /// 字体大小
        /// </summary>
        public float textSize { get; set; }

        /// <summary>
        /// 宽度(图片使用)
        /// </summary>
        public float Width { get; set; }

        /// <summary>
        /// 高度(图片使用)
        /// </summary>
        public float Height { get; set; }
        #endregion


        public iTextPdf()
        {
            _path = string.Format("{0}/template.pdf", System.Web.HttpContext.Current.Request.MapPath(System.Web.Configuration.WebConfigurationManager.AppSettings["ConfigDir"]));
        }

        public iTextPdf(string path)
        {
            _path = path;
        }

        public void SavePdf(List<iTextPdf> pdflist,string savefile)
        {
            using (Stream inputPdfStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read))   //打开pdf模板
            using (Stream outputPdfStream = new FileStream(savefile, FileMode.Create, FileAccess.Write, FileShare.None))    //创建新的pdf对象用于保存
            {
                var reader = new PdfReader(inputPdfStream);
                var stamper = new PdfStamper(reader, outputPdfStream);
                var list = pdflist.OrderBy(x => x.PageIndex);   //对页号运行排序
                //FontFactory.RegisterDirectory("C:\\WINDOWS\\Fonts");  //字体目录
                list.Select(x => x.PageIndex).Distinct().ToList().ForEach(page =>
                {   //先按页进行遍历,可以减少实例化pdfContentByte的次数,减少资源占用
                    var pdfContentByte = stamper.GetOverContent(page);
                    Rectangle pagesize = reader.GetPageSizeWithRotation(page);
                    float height = pagesize.Height;
                    list.Where(x => x.PageIndex.Equals(page)).ToList().ForEach(item =>
                    { //针对每页进行要插入的内容进行遍历
                        switch (item.Type)
                        {
                            case 1:
                            case 2:
                                string content = item.Content;
                                float fontsize = 12;    //字号
                                if (!string.IsNullOrEmpty(content))
                                {   //只处理有文字内容的
                                    if ((2).Equals(item.Type))
                                    {   //对勾选的内容进行处理
                                        if ("1".Equals(content))
                                        {   //标记为1的,内容换成√,按插入文字处理
                                            content = "√"; 
                                            fontsize = 16;
                                        }
                                        else
                                        {
                                            content = "";
                                            break;
                                        }

                                    }
                                    BaseFont bfTimes = BaseFont.CreateFont(System.Web.HttpContext.Current.Request.MapPath("~/fonts/simhei.ttf"), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);   //注册字体,支持中文
                                    pdfContentByte.SetColorFill(BaseColor.BLACK);

                                    pdfContentByte.SetFontAndSize(bfTimes, fontsize);   //设置字体及字号
                                    pdfContentByte.BeginText(); //开始处理文字
                                    pdfContentByte.ShowTextAligned(Element.ALIGN_LEFT, content, item.X, height - item.Y, 0);
                                    pdfContentByte.EndText();   //文字处理达成
                                }

                                break;
                            case 4:
                            case 5:  //身份证图片
                                string imgpath = System.Web.HttpContext.Current.Request.MapPath(item.Content);  //图片物理路径
                                using (Stream inputImageStream = new FileStream(imgpath, FileMode.Open, FileAccess.Read, FileShare.Read))   //打开图片
                                {
                                    Image image = Image.GetInstance(inputImageStream);
                                    image.SetAbsolutePosition(item.X, item.Y);  //图片坐标
                                    image.ScaleAbsolute(item.Width, item.Height);   //设置图片宽度和高度
                                    pdfContentByte.AddImage(image);
                                }
                                break;
                        }
                    });
                });

                stamper.Close();    //关闭同时保存
            }
        }
    }
}

C#多线程并发处理的问题

公司某业务,需要按条来处理大批量数据,大概几万条到几十万条都有可能。这个是由另外一个同事写的,写完之后测试,速度、效率都非常低。我问了下,原来是直接拿这些数据进行循环处理,之后又把有问题的数据循环入库。
这就有两个瓶颈,一个是单线程处理数据,另一个就是又一次循环入库。
我给出的建议是,处理数据部分多线程,处理完数据之后直接把有问题的数据入库。可是同事用不明白多线程,那好吧,我给写个Demo吧。
这里需要用到队列(Queue)和Task或Thread。我这里使用的是ConcurrentQueue,ConcurrentQueue队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据结构。
首先,实例化一个队列,名为queue:
private ConcurrentQueue<Models.Demo> queue;
之后,给这个队列填充上测试用的数据:

//生成测试用数据列表
for (int i = 1; i <= 50000; i++)
{
    Models.Demo dat = new Models.Demo() { id = i, value = Libs.Rand.RndCode(8) };
    queue.Enqueue(dat);
    Thread.Sleep(1);    //这里是随机数生成时需要
}

下面是处理启用多线程来处理数据了

int threadcount=10; //开启10个线程

for(int i=0;i<threadcount;i++)
{
    string filename = string.Format("task{0}.txt", i);
    filename = System.Web.HttpContext.Current.Request.MapPath(string.Format("~/file/{0}", filename));
    Task.Factory.StartNew(() =>
    {        
        Models.Demo demo = new Models.Demo();
        StringBuilder sb = new StringBuilder();
        int j = 0;
    
        while (queue.TryDequeue(out demo))
        {
            //处理数据
            if (demo != null)
                sb.AppendLine(string.Format("{0}.{1}", demo.id, demo.value));

            if (j % 100 == 0 ||  (queue.Count.Equals(0) && j<100))
            {   //每100条写一次文件,并暂停100毫秒
                Libs.FileObj.WriteFile(filename, sb.ToString());
                sb = new StringBuilder();
                Thread.Sleep(100); 
            }
            j++;
        }
    });
}

这就搞定了。以上。

提高WebRequest方法的并发限制

在C#中,WebRequest方法和WebClient方法,在多线程时,对并发请求数量有一个默认限制,这个限制与操作系统相关,在Windows XP/Windows 7等PC系统上默认为2个,而在Windows 2008等服务器系统中,默认为10个,也就是说在出现高并发的环境中,使用WebRequest方法来进行POST或GET请求时,最多只能同时发送10个,剩下的都在排队。出现这个问题的原因是,在HTTP 1.0和HTTP 1.1规定最大连接数就是2,就一直延用到现在。
解决方法:
在程序中设置:

System.Net.ServicePointManager.DefaultConnectionLimit = 512;  //建议最高不要超过1024,具体看使用环境是否需要

或者在配置中设置:

<configuration>
    <system.net>
        <connectionManagement>
            <add address = "http://www.google.com" maxconnection = "512" ></add>
            <add address = "*" maxconnection = "512" ></add>
        </connectionManagement>
    </system.net>
</configuration>

以上。

分类

最新文章

最近回复

归档

标签云

C# .net core asp.net 情感 SQL mongodb sql server EasyUI linux 身份验证 typecho .net sql注入 安全 kms 激活 MVC https IIS 高并发 IE 坑爹 服务器 mysql Combobox Datagrid 口语 数据抓取 远程下载

其它