8月 01

设置Symbol Search Path

SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols

Open Crash Dump,选择我们抓取到的dmp文件

加载SOS调试扩展,加载之后才可以做各种调试,根据不同的版本选择加载不同的文件

.load C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/sos.dll
.load C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/sos.dll

如果是64位

.load C:\Windows\Microsoft.NET\Framework64\v2.0.50727\SOS.dll
.load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SOS.dll

 

查看运行环境版本信息

lmvm mscorwks

另外,windbg默认的字体真的很难受

View–>Font 可以设置字体

 

颜色的话一般设置命令行颜色不同即可

View–>Options–>Colors

    "Prompt level command window text"

    "Prompt level command windows text background"

这样调完之后看着舒服多了

written by ocean

7月 11

 一个标签中,同时有 col-xs , col-sm , col-md , col-lg

.col-xs- 超小屏幕 手机 (<768px)

.col-sm- 小屏幕 平板 (≥768px)

.col-md- 中等屏幕 桌面显示器 (≥992px)

.col-lg- 大屏幕 大桌面显示器 (≥1200px)

<div class="col-xs-12 col-sm-9 col-md-6 col-lg-3">                        
</div>

当屏幕尺寸

小于 768px 的时候,用 col-xs-12 类对应的样式;

在 768px 到 992px 之间的时候,用 col-sm-9 类对应的样式;

在 992px 到 1200px 之间的时候,用 col-md-6 类对应的样式;

大于 1200px 的时候,用 col-lg-3 类对应的样式;

written by ocean

6月 28

之前有记录一篇提取网页正文的算法

提取网页正文的通用算法

 

发现在一些文章上提取效果不是很理想。后来发现了 Raedability网站(www.readability.com)

它最引以为傲的就是其强大的解析引擎, 号称世界上最强大的文本解析神器. Safari中的"阅读器"功能就是用它来实现的! 他们还提供了API可以调用解析器的功能

 

网上找了一个包装代理类,发现已经失效了。自己写了一个,依然用的.net core

    public static class ReadabilityProxy
    { 
        private static HttpClient httpClient = new HttpClient();
        public static Article Parse(string url, string token) //token就是各位的appkey
        {
            var encUrl = WebUtility.UrlEncode(url);
            Uri u = new Uri(string.Format("https://mercury.postlight.com/parser?url={0}", encUrl, token));
            httpClient.DefaultRequestHeaders.Add("x-api-key", token);
            var json = httpClient.GetStringAsync(u).Result;
            var article = Newtonsoft.Json.JsonConvert.DeserializeObject<Article>(json);
            article.Decode();
            return article;
        } 
    }
    
    public class Article
    {
        public string Domain;
        public string Next_Page_Id;
        public string Url;
        public string Content;
        public string Short_Url;
        public string Excerpt;
        public string Direction;
        public int Word_Count;
        public int Total_Pages;
        public string Date_Published;
        public string Dek;
        public string Lead_Image_Url;
        public string Title;
        public int Rendered_Pages;

        public virtual void Decode()
        {
            this.Excerpt = WebUtility.HtmlDecode(this.Excerpt);
            this.Content = WebUtility.HtmlDecode(this.Content);
        }
    }

调用方式

    static void Main(string[] args)
    {
        var article = ReadabilityProxy.Parse("http://blog.wx6.org/", 
            "5yf880mid1fMlpVUEDFaw3mquGCuzzzxAJhrqn1x");
        article.Decode();
        Console.WriteLine(article.Title);
        Console.WriteLine(article.Excerpt);
        Console.WriteLine(article.Content);
        Console.ReadLine();
    }

 

不过实际效果发现也不是很完美 

written by ocean

6月 22

做采集会用到提取网页正文的功能。

找到一个 《基于行块分布函数的通用网页正文抽取算法》

已经有一个实现方式了,项目名称Html2Article 原作者不支持.net core

因为我要在 .net core 中使用,所以github上找到源代码,稍作修改

调用方式很简单

var article=Html2Article.GetArticle(html); 
Console.WriteLine(article.ContentWithTags);

 

纪录下来改过的源代码

   /// <summary>
    /// 文章正文数据模型
    /// </summary>
    public class Article
    {
        /// <summary>
        /// 文章标题
        /// </summary>
        public string Title { get; set; }
        /// <summary>
        /// 正文文本
        /// </summary>
        public string Content { get; set; }
        /// <summary>
        /// 带标签正文
        /// </summary>
        public string ContentWithTags { get; set; }
        /// <summary>
        /// 文章发布时间
        /// </summary>
        public DateTime PublishDate { get; set; }
    }
     
    public class Html2Article
    {
        #region 参数设置

        // 正则表达式过滤:正则表达式,要替换成的文本
        private static readonly string[][] Filters =
        {
            new[] { @"(?is)<script.*?>.*?</script>", "" },
            new[] { @"(?is)<style.*?>.*?</style>", "" },
            new[] { @"(?is)<!--.*?-->", "" },    // 过滤Html代码中的注释
            // 针对链接密集型的网站的处理,主要是门户类的网站,降低链接干扰
            new[] { @"(?is)</a>", "</a>\n"}
        };

        private static bool _appendMode = false;
        /// <summary>
        /// 是否使用追加模式,默认为false
        /// 使用追加模式后,会将符合过滤条件的所有文本提取出来
        /// </summary>
        public static bool AppendMode
        {
            get { return _appendMode; }
            set { _appendMode = value; }
        }

        private static int _depth = 6;
        /// <summary>
        /// 按行分析的深度,默认为6
        /// </summary>
        public static int Depth
        {
            get { return _depth; }
            set { _depth = value; }
        }

        private static int _limitCount = 180;
        /// <summary>
        /// 字符限定数,当分析的文本数量达到限定数则认为进入正文内容
        /// 默认180个字符数
        /// </summary>
        public static int LimitCount
        {
            get { return _limitCount; }
            set { _limitCount = value; }
        }

        // 确定文章正文头部时,向上查找,连续的空行到达_headEmptyLines,则停止查找
        private static int _headEmptyLines = 2;
        // 用于确定文章结束的字符数
        private static int _endLimitCharCount = 20;

        #endregion

        /// <summary>
        /// 从给定的Html原始文本中获取正文信息
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static Article GetArticle(string html)
        {
            // 如果换行符的数量小于10,则认为html为压缩后的html
            // 由于处理算法是按照行进行处理,需要为html标签添加换行符,便于处理
            int tagCount = 0;
            for (int index = 0; index < html.Length; index++)
            {
                if (html[index] == '\n')
                {
                    tagCount++;
                }
            }
            if (tagCount < 10)
            {
                html = html.Replace(">", ">\n");
            }

            // 获取html,body标签内容
            string body = "";
            string bodyFilter = @"(?is)<body.*?</body>";
            Match m = Regex.Match(html, bodyFilter);
            if (m.Success)
            {
                body = m.ToString();
            }
            // 过滤样式,脚本等不相干标签
            foreach (var filter in Filters)
            {
                body = Regex.Replace(body, filter[0], filter[1]);
            }
            // 标签规整化处理,将标签属性格式化处理到同一行
            // 处理形如以下的标签:
            //  <a 
            //   href='http://www.baidu.com'
            //   class='test'
            // 处理后为
            //  <a href='http://www.baidu.com' class='test'>
            body = Regex.Replace(body, @"(<[^<>]+)\s*\n\s*", FormatTag);

            string content;
            string contentWithTags;
            GetContent(body, out content, out contentWithTags);

            Article article = new Article
            {
                Title = GetTitle(html),
                PublishDate = GetPublishDate(body),
                Content = content,
                ContentWithTags = contentWithTags
            };

            return article;
        }

        /// <summary>
        /// 格式化标签,剔除匹配标签中的回车符
        /// </summary>
        /// <param name="match"></param>
        /// <returns></returns>
        private static string FormatTag(Match match)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var ch in match.Value)
            {
                if (ch == '\r' || ch == '\n')
                {
                    continue;
                }
                sb.Append(ch);
            }
            return sb.ToString();
        }

        /// <summary>
        /// 获取时间
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        private static string GetTitle(string html)
        {
            string titleFilter = @"<title>[\s\S]*?</title>";
            string h1Filter = @"<h1.*?>.*?</h1>";
            string clearFilter = @"<.*?>";

            string title = "";
            Match match = Regex.Match(html, titleFilter, RegexOptions.IgnoreCase);
            if (match.Success)
            {
                title = Regex.Replace(match.Groups[0].Value, clearFilter, "");
            }

            // 正文的标题一般在h1中,比title中的标题更干净
            match = Regex.Match(html, h1Filter, RegexOptions.IgnoreCase);
            if (match.Success)
            {
                string h1 = Regex.Replace(match.Groups[0].Value, clearFilter, "");
                if (!String.IsNullOrEmpty(h1) && title.StartsWith(h1))
                {
                    title = h1;
                }
            }
            return title;
        }

        /// <summary>
        /// 获取文章发布日期
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        private static DateTime GetPublishDate(string html)
        {
            // 过滤html标签,防止标签对日期提取产生影响
            string text = Regex.Replace(html, "(?is)<.*?>", "");
            Match match = Regex.Match(
                text,
                @"((\d{4}|\d{2})(\-|\/)\d{1,2}\3\d{1,2})(\s?\d{2}:\d{2})?|(\d{4}年\d{1,2}月\d{1,2}日)(\s?\d{2}:\d{2})?",
                RegexOptions.IgnoreCase);

            DateTime result = new DateTime(1900, 1, 1);
            if (match.Success)
            {
                try
                {
                    string dateStr = "";
                    for (int i = 0; i < match.Groups.Count; i++)
                    {
                        dateStr = match.Groups[i].Value;
                        if (!String.IsNullOrEmpty(dateStr))
                        {
                            break;
                        }
                    }
                    // 对中文日期的处理
                    if (dateStr.Contains("年"))
                    {
                        StringBuilder sb = new StringBuilder();
                        foreach (var ch in dateStr)
                        {
                            if (ch == '年' || ch == '月')
                            {
                                sb.Append("/");
                                continue;
                            }
                            if (ch == '日')
                            {
                                sb.Append(' ');
                                continue;
                            }
                            sb.Append(ch);
                        }
                        dateStr = sb.ToString();
                    }
                    result = Convert.ToDateTime(dateStr);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                if (result.Year < 1900)
                {
                    result = new DateTime(1900, 1, 1);
                }
            }
            return result;
        }

        /// <summary>
        /// 从body标签文本中分析正文内容
        /// </summary>
        /// <param name="bodyText">只过滤了script和style标签的body文本内容</param>
        /// <param name="content">返回文本正文,不包含标签</param>
        /// <param name="contentWithTags">返回文本正文包含标签</param>
        private static void GetContent(string bodyText, out string content, out string contentWithTags)
        {
            string[] orgLines = null;   // 保存原始内容,按行存储
            string[] lines = null;      // 保存干净的文本内容,不包含标签

            orgLines = bodyText.Split('\n');
            lines = new string[orgLines.Length];
            // 去除每行的空白字符,剔除标签
            for (int i = 0; i < orgLines.Length; i++)
            {
                string lineInfo = orgLines[i];
                // 处理回车,使用[crlf]做为回车标记符,最后统一处理
                lineInfo = Regex.Replace(lineInfo, "(?is)</p>|<br.*?/>", "[crlf]");
                lines[i] = Regex.Replace(lineInfo, "(?is)<.*?>", "").Trim();
            }

            StringBuilder sb = new StringBuilder();
            StringBuilder orgSb = new StringBuilder();

            int preTextLen = 0;         // 记录上一次统计的字符数量
            int startPos = -1;          // 记录文章正文的起始位置
            for (int i = 0; i < lines.Length - _depth; i++)
            {
                int len = 0;
                for (int j = 0; j < _depth; j++)
                {
                    len += lines[i + j].Length;
                }

                if (startPos == -1)     // 还没有找到文章起始位置,需要判断起始位置
                {
                    if (preTextLen > _limitCount && len > 0)    // 如果上次查找的文本数量超过了限定字数,且当前行数字符数不为0,则认为是开始位置
                    {
                        // 查找文章起始位置, 如果向上查找,发现2行连续的空行则认为是头部
                        int emptyCount = 0;
                        for (int j = i - 1; j > 0; j--)
                        {
                            if (String.IsNullOrEmpty(lines[j]))
                            {
                                emptyCount++;
                            }
                            else
                            {
                                emptyCount = 0;
                            }
                            if (emptyCount == _headEmptyLines)
                            {
                                startPos = j + _headEmptyLines;
                                break;
                            }
                        }
                        // 如果没有定位到文章头,则以当前查找位置作为文章头
                        if (startPos == -1)
                        {
                            startPos = i;
                        }
                        // 填充发现的文章起始部分
                        for (int j = startPos; j <= i; j++)
                        {
                            sb.Append(lines[j]);
                            orgSb.Append(orgLines[j]);
                        }
                    }
                }
                else
                {
                    //if (len == 0 && preTextLen == 0)    // 当前长度为0,且上一个长度也为0,则认为已经结束
                    if (len <= _endLimitCharCount && preTextLen < _endLimitCharCount)    // 当前长度为0,且上一个长度也为0,则认为已经结束
                    {
                        if (!_appendMode)
                        {
                            break;
                        }
                        startPos = -1;
                    }
                    sb.Append(lines[i]);
                    orgSb.Append(orgLines[i]);
                }
                preTextLen = len;
            }

            string result = sb.ToString();
            // 处理回车符,更好的将文本格式化输出
            content = result.Replace("[crlf]", Environment.NewLine);
            content =  WebUtility.HtmlDecode(content);
            // 输出带标签文本
            contentWithTags = orgSb.ToString();
        }


        /// <summary>
        /// 基于baseUrl,补全html代码中的链接
        /// </summary>
        /// <param name="baseUrl"></param>
        /// <param name="html"></param>
        public static string FixUrl(string baseUrl, string html)
        {
            html = Regex.Replace(html, "(?is)(href|src)=(\"|\')([^(\"|\')]+)(\"|\')", (match) =>
            {
                string org = match.Value;
                string link = match.Groups[3].Value;
                if (link.StartsWith("http"))
                {
                    return org;
                }

                try
                {
                    Uri uri = new Uri(baseUrl);
                    Uri thisUri = new Uri(uri, link);
                    string fullUrl = String.Format("{0}=\"{1}\"", match.Groups[1].Value, thisUri.AbsoluteUri);
                    return fullUrl;
                }
                catch (Exception)
                {
                    return org;
                }
            });
            return html;
        }

    }

 

written by ocean

1月 16

平时自己的项目都是打包管理的。从来不用代码管理工具。

因为就自己开发嘛,完全用不上。不过最近因为自己家里电脑和公司电脑上都会写写代码,合并代码就成了一个问题。实在不想记住改过哪些。就准备用用源代码管理。

第一想法是用一个公共的源代码管理系统。 

OSChina的码云有研究过,实在信不过国内的人。(虽然不重要,但是也不想自己的代码外泄)

微软的TFS,家里的长城宽带又连接很慢,经常失败。于是网上找呀找,就找到了这么一个好玩意。

Gidder,下载地址

https://m.downloadatoz.com/gidder-beta/net.antoniy.gidder.beta/

请自己科学上网

刚好有个旧的小米手机,直接拿来当服务器了。

安装完毕,在手机上打开,创建User,创建Repository,关联User和Repository,OK。

手机连接wifi,点击Start,显示

172.28.3.70:6666 这个就是地址。

接下来PC上操作。

首先创建一个项目,在Solution上右键“Add Project to Source Control”。

进入Team Explorer面板。

选择Sync,选择“Public to Remote Repository”下的“Public Git Repo”

地址输入

http://172.28.3.70:6666/zuotu5.git

written by ocean

11月 15

标题好拗口。

之前记录过  DapperDapper.SimpleCRUD 的使用方法,不过其提供的Insert方法只能支持包含自增ID主键的表。

实际项目中经常会有无自增的主键的表,查了很久源码,发现没有实现,就自己写了一个,顺便上传到github,人人为我,我为人人。

开源地址

https://github.com/ysuhy/Dapper.SimpleCRUD

written by ocean

10月 21

这里使用到了croppic这个插件

官方网址

http://www.croppic.net/

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="croppic/assets/css/bootstrap.css" rel="stylesheet" />
    <link href="croppic/assets/css/croppic.css" rel="stylesheet" /> 
    <script src="http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="croppic/croppic.min.js"></script> 
</head>
<body>  
    	<div id="croppic"></div>
					<span class="btn" id="cropContainerHeaderButton">click here to try it</span> 
    <script>
        var croppicHeaderOptions = {
            uploadUrl:'dopic.aspx',
            cropData: {
                "dummyData": 1,
                "dummyData2": "asdas"
            }, 
            cropUrl: 'img_crop_to_file.php',
            customUploadButtonId: 'cropContainerHeaderButton',
            modal: false,
            processInline: true,
            loaderHtml: '<div class="loader bubblingG"><span id="bubblingG_1"></span><span id="bubblingG_2"></span><span id="bubblingG_3"></span></div> ',
            onBeforeImgUpload: function () { console.log('onBeforeImgUpload') },
            onAfterImgUpload: function () { console.log('onAfterImgUpload') },
            onImgDrag: function () { console.log('onImgDrag') },
            onImgZoom: function () { console.log('onImgZoom') },
            onBeforeImgCrop: function () { console.log('onBeforeImgCrop') },
            onAfterImgCrop: function () { console.log('onAfterImgCrop') },
            onReset: function () { console.log('onReset') },
            onError: function (errormessage) { console.log('onError:' + errormessage) }
        }
        var croppic = new Croppic('croppic', croppicHeaderOptions);

    </script>

</body>
</html>

后台处理代码

    public partial class DoPic : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var imgUrl = Request["imgUrl"].ToString();

            // original sizes
            var imgInitW = Request["imgInitW"];
            var imgInitH = Request["imgInitH"];


            // resized sizes
            var imgW =GetInt( Request["imgW"]);
            var imgH =GetInt( Request["imgH"]); 
            // offsets
            var imgY1 = GetInt(Request["imgY1"]);
            var imgX1 = GetInt(Request["imgX1"]); 
            // crop box 
            var cropW = GetInt(Request["cropW"]);
            var cropH = GetInt(Request["cropH"]);
            // rotation angle 
            var rotation = GetInt(Request["rotation"]); 
            imgUrl = imgUrl.Substring(imgUrl.IndexOf(',')+1);
             byte[] arr = Convert.FromBase64String(imgUrl);

             MagickImage mi = new MagickImage(arr);
             mi.Resize( new MagickGeometry(imgW + "x" + imgH));

             mi.Rotate(rotation);
             mi.Crop(new MagickGeometry(imgX1, imgY1, cropW, cropH));

             mi.Write(@"D:\Test\TestDemo\WebApplication1\1.png");

        }


        public static int GetInt(string input){
            double d=double.Parse(input);
            int r=(int)d;
            return r;
        }
    }

written by ocean

9月 22

密码保护:GraphicsMagick使用方法总结

第三方组件 要查看留言请输入您的密码。

这是一篇受密码保护的文章,您需要提供访问密码:

written by ocean

9月 14

自从用了Dapper之后,深深地爱上它并且不可自拔。 

今天又发现了一个很好的orm组件,相较于dapper来说,多了很多api,在某些场景下可以省很多事。发现自己越来越懒了,

项目主页

http://www.toptensoftware.com/petapoco/

优点

微小,没有依赖项……单个的C#文件可以方便的添加到任何项目中。
工作于严格的没有装饰的Poco类,和几乎全部加了特性的Poco类
Insert/Delete/Update/Save and IsNew 等帮助方法。
分页支持:自动得到总行数和数据
支持简单的事务
更好的支持参数替换,包括从对象属性中抓取命名的参数。
很好的性能,剔除了Linq,并通过Dynamic方法快速的为属性赋值
T4模板自动生成Poco类
查询语言是Sql……不支持别扭的fluent或Linq语法(仁者见仁,智者见智)
包含一个低耦合的Sql Builder类,让内联的Sql更容易书写
为异常信息记录、值转换器安装和数据映射提供钩子。(Hooks for logging exceptions, installing value converters and mapping columns to properties without attributes.)
兼容SQL Server, SQL Server CE, MySQL, PostgreSQL and Oracle。
可以在.NET 3.5 或Mono 2.6或更高版本上运行
在.NET 4.0 和Mono 2.8下支持dynamic
NUnit单元测试
开源(Apache License)
所有功能大约用了1500行代码

 

Nuget安装

Install-Package PetaPoco

 

以下内容未做测试 

定义一个poco类

public class article
{    
        public long article_id { get; set; }    
        public string title { get; set; }    
        public DateTime date_created { get; set; }    
        public bool draft { get; set; }    
        public string content { get; set; }
}

接下来,创建一个PetaPoco.Database,来执行查询:

// Create a PetaPoco database object
var db=new PetaPoco.Database("connectionStringName");
// Show all articles    
foreach (var a in db.Query<article>("SELECT * FROM articles"))
{
        Console.WriteLine("{0} - {1}", a.article_id, a.title);
}

得到一个scalar:

long count=db.ExecuteScalar<long>("SELECT Count(*) FROM articles");

得到一行记录:

var a = db.SingleOrDefault<article>("SELECT * FROM articles WHERE article_id=@0", 123));

获取分页数据:

var result=db.Page<article>(1, 20, // <-- page number and items per page
        "SELECT * FROM articles WHERE category=@0 ORDER BY date_posted DESC", "coolstuff");

你将会得到一个PagedFetch对象:

public class Page<T> where T:new()
{    
        public long CurrentPage { get; set; }    
        public long ItemsPerPage { get; set; }    
        public long TotalPages { get; set; }    
        public long TotalItems { get; set; }    
        public List<T> Items { get; set; }
}

使用Execute 方法执行一个不带查询的命令:

db.Execute("DELETE FROM articles WHERE draft<>0");

在插入一条记录时,你需要指定插入的表名和主键:

// Create the article
var a=new article();
a.title="My new article";
a.content="PetaPoco was here";
a.date_created=DateTime.UtcNow;
// Insert it
db.Insert("articles", "article_id", a);
// by now a.article_id will have the id of the new article

更新记录也一样:

// Get a record
var a=db.SingleOrDefault<article>("SELECT * FROM articles WHERE article_id=@0", 123);
// Change it
a.content="PetaPoco was here again";
// Save it
db.Update("articles", "article_id", a);

或者你可以传一个匿名类来更新一部分字段。下面的代码只更新article的title字段:

db.Update("articles", "article_id", new { title="New title" }, 123);

删除:

// Delete an article extracting the primary key from a record
db.Delete("articles", "article_id", a);
// Or if you already have the ID elsewhere
db.Delete("articles", "article_id", null, 123);

在上面的例子中,必须指明表名和主键是很烦人的,你可以在你的Poco类中附加这些信息:

// Represents a record in the "articles" table
[PetaPoco.TableName("articles")]
[PetaPoco.PrimaryKey("article_id")]
public class article
{    
        public long article_id { get; set; }    
        public string title { get; set; }    
        public DateTime date_created { get; set; }    
        public bool draft { get; set; }    
        public string content { get; set; }
}

简化后的insert、update、delete:

// Insert a record
var a=new article();
a.title="My new article";
a.content="PetaPoco was here";
a.date_created=DateTime.UtcNow;
db.Insert(a);
// Update it
a.content="Blah blah";
db.Update(a);
// Delete 
itdb.Delete(a);

 

事务相当的简单:

using (var scope=db.Transaction)
{
    // Do transacted updates here

    // Commit
    scope.Complete();
}

你也可以根据条件构建SQL:

var id=123;
var sql=PetaPoco.Sql.Builder
    .Append("SELECT * FROM articles")
    .Append("WHERE article_id=@0", id);

if(start_date.HasValue)
    sql.Append("AND date_created>=@0", start_date.Value);

if(end_date.HasValue)
    sql.Append("AND date_created<=@0", end_date.Value);

var a=db.Query<article>(sql)

var sql=PetaPoco.Sql.Builder()
            .Select("*")
            .From("articles")
            .Where("date_created < @0",DateTime.UtcNow)
            .OrderBy("date_created DESC");

注意到每个append调用都用到餐厨@0了吗?PetaPoco构建整个列表的参数,将这些参数索引更新到内部。你也可以使用命名参数,然后他会在传递的参数中找到合适的属性名。

sql.Append("AND date_created>=@start AND date_created<=@end", 
                new 
                { 
                    start=DateTime.UtcNow.AddDays(-2), 
                    end=DateTime.UtcNow 
                }
            );



written by ocean

6月 27

公司做个监控的小东西,图省事,我用log4net打了txt的日志

使用了 零配置log4net增强使用

结果现在需要统计数据,我之后悲催的分解txt,打算导出成excel

发现了一一个好东西 NPOI

NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。
使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写。NPOI是构建在POI 3.x版本之上的,它可以在没有安装Office的情况下对Word/Excel文档进行读写操作。

现在简单记录一下使用的代码

首先需要安装npoi组件,使用nuget

在Package Manager Console中输入命令

Install-Package NPOI

使用DataTable转Excel,这段代码来自网络

private static void GridToExcelByNPOI(DataTable dt, string strExcelFileName)
{
    try
    {
        HSSFWorkbook workbook = new HSSFWorkbook();
        ISheet sheet = workbook.CreateSheet("Sheet1");
        ICellStyle HeadercellStyle = workbook.CreateCellStyle();
        HeadercellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
        HeadercellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
        HeadercellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
        HeadercellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
        HeadercellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
        //字体
        NPOI.SS.UserModel.IFont headerfont = workbook.CreateFont();
        headerfont.Boldweight = (short)FontBoldWeight.Bold;
        HeadercellStyle.SetFont(headerfont);

        //用column name 作为列名
        int icolIndex = 0;
        IRow headerRow = sheet.CreateRow(0);
        foreach (DataColumn item in dt.Columns)
        {
            ICell cell = headerRow.CreateCell(icolIndex);
            cell.SetCellValue(item.ColumnName);
            cell.CellStyle = HeadercellStyle;
            icolIndex++;
        }
        ICellStyle cellStyle = workbook.CreateCellStyle();
        //为避免日期格式被Excel自动替换,所以设定 format 为 『@』 表示一率当成text來看
        cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@");
        cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
        cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
        cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
        cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;

        NPOI.SS.UserModel.IFont cellfont = workbook.CreateFont();
        cellfont.Boldweight = (short)FontBoldWeight.Normal;
        cellStyle.SetFont(cellfont);
        //建立内容行
        int iRowIndex = 1;
        int iCellIndex = 0;
        foreach (DataRow Rowitem in dt.Rows)
        {
            IRow DataRow = sheet.CreateRow(iRowIndex);
            foreach (DataColumn Colitem in dt.Columns)
            {
                ICell cell = DataRow.CreateCell(iCellIndex);
                cell.SetCellValue(Rowitem[Colitem].ToString());
                cell.CellStyle = cellStyle;
                iCellIndex++;
            }
            iCellIndex = 0;
            iRowIndex++;
        }
        //自适应列宽度
        for (int i = 0; i < icolIndex; i++)
        {
            sheet.AutoSizeColumn(i);
        }
        //写Excel
        FileStream file = new FileStream(strExcelFileName, FileMode.OpenOrCreate);
        workbook.Write(file);
        file.Flush();
        file.Close();
        // MessageBox.Show(m_Common_ResourceManager.GetString("Export_to_excel_successfully"), m_Common_ResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (Exception ex)
    {
        // ILog log = LogManager.GetLogger("Exception Log");
        //   log.Error(ex.Message + Environment.NewLine + ex.StackTrace);
        //记录AuditTrail
        //   CCFS.Framework.BLL.AuditTrailBLL.LogAuditTrail(ex);
        //  MessageBox.Show(m_Common_ResourceManager.GetString("Export_to_excel_failed"), m_Common_ResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    finally {   }
}

调用代码

var files= Directory.GetFiles(path);
StringBuilder sb = new StringBuilder();
DataTable tb = new DataTable();
tb.Columns.Add(new DataColumn("Start"));
tb.Columns.Add(new DataColumn("End"));
tb.Columns.Add(new DataColumn("Duration"));
tb.Columns.Add(new DataColumn("IsOk"));
tb.Columns.Add(new DataColumn("Data"));
foreach (var file in files)
{
    var lines = File.ReadAllLines(file);
    foreach (var line in lines)
    {
        if (line.Contains("[INFO]"))
        {
            var dr = tb.NewRow();
            var json = line.Substring(line.IndexOf("[INFO]")+9);
            var obj = JsonConvert.DeserializeObject<ResultInfo>(json);
            dr["Start"] = obj.Start;
            dr["End"] = obj.End;
            dr["Duration"] = obj.Duration;
            dr["IsOk"] = obj.IsOk;
            dr["Data"] =obj.Data;
            tb.Rows.Add(dr);
        }                
    }                   
}

GridToExcelByNPOI(tb, @"C:\Users\heyang\Desktop\IRisk\1.xls");

written by ocean \\ tags: ,