|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/// <summary> /// 更新点击量 /// </summary> /// <param name="id"></param> /// <param name="num"></param> public void UpdateHits(int id, int num) { const string sql = @"update articles set hits+=@Hits where id=@Id"; object[] args = { new SqlParameter { ParameterName = "@Hits", Value = num}, new SqlParameter { ParameterName = "@Id", Value=id} }; _db.Database.ExecuteSqlCommand(sql, args); } |
游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合的。而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服。 正常面向集合的思维方式是: 而对于游标来说: 这也是为什么游标是邪恶的,它会使开发人员变懒,懒得去想用面向集合的查询方式实现某些功能. 同样的,在性能上,游标会吃更多的内存,减少可用的并发,占用宽带,锁定资源,当然还有更多的代码量…… 从游标对数据库的读取方式来说,不难看出游标为什么占用更多的资源,打个比方: 当你从ATM取钱的时候,是一次取1000效率更高呢,还是取10次100? 既然游标这么“邪恶”,为什么还要学习游标 我个人认为存在既是合理.归结来说,学习游标原因我归纳为以下2点 1.现存系统有一些游标,我们查询必须通过游标来实现 2.作为一个备用方式,当我们穷尽了while循环,子查询,临时表,表变量,自建函数或其他方式扔来无法实现某些查询的时候,使用游标实现. T-SQL中游标的生命周期以及实现 在T-SQL中,游标的生命周期由5部分组成 1.定义一个游标 在T-SQL中,定义一个游标可以是非常简单,也可以相对复杂,取决于游标的参数.而游标的参数设置取决于你对游标原理的了解程度. 游标其实可以理解成一个定义在特定数据集上的指针,我们可以控制这个指针遍历数据集,或者仅仅是指向特定的行,所以游标是定义在以Select开始的数据集上的: T-SQL中的游标定义在MSDN中如下:
|
1 2 3 4 5 6 7 |
<a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=DECLARE&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">DECLARE</a> cursor_name <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=CURSOR&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">CURSOR</a> [ <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=LOCAL&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">LOCAL</a> | <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=GLOBAL&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">GLOBAL</a> ] [ FORWARD_ONLY | <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=SCROLL&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">SCROLL</a> ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] [ TYPE_WARNING ] <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=FOR&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">FOR</a> select_statement [ <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=FOR&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">FOR</a> <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=UPDATE&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">UPDATE</a> [ <a href="http://search.microsoft.com/default.asp?so=RECCNT&siteid=us%2Fdev&p=1&nq=NEW&qu=OF&IntlSearch=&boolean=PHRASE&ig=01&i=09&i=99">OF</a> column_name [ ,...n ] ] ] [;] |
看起来很让人头痛是吧.下面仔细讲一下如何定义游标: 游标分为游标类型和游标变量,对于游标变量来说,遵循T-SQL变量的定义方法(啥,不知道T-SQL变量定义的规则?参考我前面的博文).游标变量支持两种方式赋值,定义时赋值和先定义后赋值,定义游标变量像定义其他局部变量一样,在游标前加”@”,注意,如果定义全局的游标,只支持定义时直接赋值,并且不能在游标名称前面加“@”,两种定义方式如下: 下面我们来看游标定义的参数: LOCAL和GLOBAL二选一 LOCAL意味着游标的生存周期只在批处理或函数或存储过程中可见,而GLOBAL意味着游标对于特定连接作为上下文,全局内有效,例如: 如果不指定游标作用域,默认作用域为GLOBAL FORWARD_ONLY 和 SCROLL 二选一 FORWARD_ONLY意味着游标只能从数据集开始向数据集结束的方向读取,FETCH NEXT是唯一的选项,而SCROLL支持游标在定义的数据集中向任何方向,或任何位置移动,如下图: STATIC KEYSET DYNAMIC 和 FAST_FORWARD 四选一 这四个关键字是游标所在数据集所反应的表内数据和游标读取出的数据的关系 STATIC意味着,当游标被建立时,将会创建FOR后面的SELECT语句所包含数据集的副本存入tempdb数据库中,任何对于底层表内数据的更改不会影响到游标的内容. DYNAMIC是和STATIC完全相反的选项,当底层数据库更改时,游标的内容也随之得到反映,在下一次fetch中,数据内容会随之改变 KEYSET可以理解为介于STATIC和DYNAMIC的折中方案。将游标所在结果集的唯一能确定每一行的主键存入tempdb,当结果集中任何行改变或者删除时,@@FETCH_STATUS会为-2,KEYSET无法探测新加入的数据 FAST_FORWARD可以理解成FORWARD_ONLY的优化版本.FORWARD_ONLY执行的是静态计划,而FAST_FORWARD是根据情况进行选择采用动态计划还是静态计划,大多数情况下FAST_FORWARD要比FORWARD_ONLY性能略好. READ_ONLY SCROLL_LOCKS OPTIMISTIC 三选一 READ_ONLY意味着声明的游标只能读取数据,游标不能做任何更新操作 […]
View Details整理一下,关于游标,MSDN有: 过 Transact-SQL 服务器游标检索特定行。 参数 NEXT 紧跟当前行返回结果行,并且当前行递增为返回行。如果 FETCH NEXT 为对游标的第一次提取操作,则返回结果集中的第一行。NEXT 为默认的游标提取选项。 PRIOR 返回紧邻当前行前面的结果行,并且当前行递减为返回行。如果 FETCH PRIOR 为对游标的第一次提取操作,则没有行返回并且游标置于第一行之前。 FIRST 返回游标中的第一行并将其作为当前行。 LAST 返回游标中的最后一行并将其作为当前行。 ABSOLUTE { n | @nvar} 如果 n 或 @nvar 为正,则返回从游标头开始向后的第 n 行,并将返回行变成新的当前行。如果 n 或 @nvar为负,则返回从游标末尾开始向前的第 n 行,并将返回行变成新的当前行。如果 n 或 @nvar 为 0,则不返回行。n 必须是整数常量,并且 @nvar 的数据类型必须为 smallint、tinyint 或 int。 RELATIVE { n | @nvar} 如果 n 或 @nvar 为正,则返回从当前行开始向后的第 n 行,并将返回行变成新的当前行。如果 n 或 @nvar为负,则返回从当前行开始向前的第 n 行,并将返回行变成新的当前行。如果 n 或 @nvar 为 0,则返回当前行。在对游标进行第一次提取时,如果在将 n 或 @nvar 设置为负数或 0 的情况下指定 FETCH RELATIVE,则不返回行。n 必须是整数常量,@nvar 的数据类型必须为 smallint、tinyint 或 int。 GLOBAL 指定 cursor_name 是指全局游标。 cursor_name 要从中进行提取的打开的游标的名称。如果全局游标和局部游标都使用 cursor_name 作为它们的名称,那么指定 GLOBAL 时,cursor_name 指的是全局游标;未指定 GLOBAL 时,cursor_name 指的是局部游标。 @ cursor_variable_name 游标变量名,引用要从中进行提取操作的打开的游标。 INTO @variable_name[ ,…n] 允许将提取操作的列数据放到局部变量中。列表中的各个变量从左到右与游标结果集中的相应列相关联。各变量的数据类型必须与相应的结果集列的数据类型匹配,或是结果集列数据类型所支持的隐式转换。变量的数目必须与游标选择列表中的列数一致。 注释 如果 SCROLL 选项未在 ISO 样式的 DECLARE CURSOR 语句中指定,则 NEXT 是唯一支持的 FETCH 选项。如果在 ISO 样式的 DECLARE CURSOR 语句中指定了 SCROLL 选项,则支持所有 FETCH 选项。 如果使用 Transact-SQL DECLARE 游标扩展插件,则应用下列规则: 如果指定了 FORWARD_ONLY 或 FAST_FORWARD,则 NEXT 是唯一受支持的 FETCH 选项。 如果未指定 DYNAMIC、FORWARD_ONLY 或 FAST_FORWARD 选项,并且指定了 KEYSET、STATIC 或 SCROLL 中的某一个,则支持所有 FETCH […]
View DetailsInsert是T-sql中常用语句,Insert INTO table(field1,field2,…) values(value1,value2,…)这种形式的在应用程序开发中必不可少。但我们在开发、测试过程中,经常会遇到需要表复制的情况,如将一个table1的数据的部分字段复制到table2中,或者将整个table1复制到table2中,这时候我们就要使用SELECT INTO 和 INSERT INTO SELECT 表复制语句了。 1.INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,…) select value1,value2,… from Table1 要求目标表Table2必须存在,由于目标表Table2已经存在,所以我们除了插入源表Table1的字段外,还可以插入常量。示例如下: —1.创建测试表 create TABLE Table1 ( a varchar(10), b varchar(10), c varchar(10), CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ( a ASC ) ) ON [PRIMARY] create TABLE Table2 ( a varchar(10), c varchar(10), d int, CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED ( a ASC ) ) ON [PRIMARY] GO —2.创建测试数据 Insert into Table1 values('赵','asds','90') Insert into Table1 values('钱','asds','100') Insert into Table1 values('孙','asds','80') Insert into Table1 values('李','asds',null) GO select * from Table2 —3.INSERT INTO SELECT语句复制表数据 Insert into Table2(a, c, d) select a,c,5 from Table1 GO —4.显示更新后的结果 select * from Table2 GO —5.删除测试表 drop TABLE Table1 drop TABLE Table2 2.SELECT INTO FROM语句 语句形式为:SELECT vale1, value2 into Table2 from Table1 要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中。示例如下: —1.创建测试表 create TABLE Table1 ( a varchar(10), b varchar(10), c varchar(10), CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ( a ASC ) ) ON [PRIMARY] GO —2.创建测试数据 Insert into Table1 values('赵','asds','90') Insert into Table1 values('钱','asds','100') Insert into Table1 values('孙','asds','80') […]
View Details|
1 2 3 |
set identity_insert 表名 ON --允许对自增列Id插入指定数据 insert into table_name(Id,Name) values(1,'test') set identity_insert 表名 OFF --关闭对自增列Id插入指定数据 |
注意: 1.set identity_insert只对当前会话生效。 2.set identity_insert 表名 ON 设置后,必须显示指定Id,否则插入错误。如insert into table_name values('111')将报错。 向自增ID插入指定值。 报错:“当 IDENTITY_INSERT 设置为 OFF 时,不能为表 ' ' 中的标识列插入显式值”。 插入语句未显示指定ID。 报错:“仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表' '中的标识列指定显式值”。 from:http://www.cnblogs.com/wanghonghu/p/4093411.html
View Details1. 一个控制台例子,实现动态生成Word。 首先,添加引用:COM->Microsoft Word 11.0 Object Library。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Microsoft.Office.Interop.Word; using System.Reflection; namespace TestWord { class Program { static void Main(string[] args) { object oMissing = System.Reflection.Missing.Value; object oEndOfDoc = "\\endofdoc"; //endofdoc是预定义的bookmark //创建一个document. Microsoft.Office.Interop.Word._Application oWord; Microsoft.Office.Interop.Word._Document oDoc; oWord = new Microsoft.Office.Interop.Word.Application(); oWord.Visible = true; oDoc = oWord.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing); //在document的开始部分添加一个paragraph. Microsoft.Office.Interop.Word.Paragraph oPara1; oPara1 = oDoc.Content.Paragraphs.Add(ref oMissing); oPara1.Range.Text = "Heading 1"; oPara1.Range.Font.Bold = 1; oPara1.Format.SpaceAfter = 24; //24 pt 行间距 oPara1.Range.InsertParagraphAfter(); //在当前document的最后添加一个paragraph Microsoft.Office.Interop.Word.Paragraph oPara2; object oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; oPara2 = oDoc.Content.Paragraphs.Add(ref oRng); oPara2.Range.Text = "Heading 2"; oPara2.Format.SpaceAfter = 6; oPara2.Range.InsertParagraphAfter(); //接着添加一个paragraph Microsoft.Office.Interop.Word.Paragraph oPara3; oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; oPara3 = oDoc.Content.Paragraphs.Add(ref oRng); oPara3.Range.Text = "This is a sentence of normal text. Now here is a table:"; oPara3.Range.Font.Bold = 0; oPara3.Format.SpaceAfter = 24; oPara3.Range.InsertParagraphAfter(); //添加一个3行5列的表格,填充数据,并且设定第一行的样式 Microsoft.Office.Interop.Word.Table oTable; Microsoft.Office.Interop.Word.Range wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; oTable = oDoc.Tables.Add(wrdRng, 3, 5, ref oMissing, ref oMissing); oTable.Range.ParagraphFormat.SpaceAfter = 6; int r, c; string strText; for (r = 1; r <= 3; r++) for (c = 1; c <= 5; c++) { strText = "r" + r + "c" + c; oTable.Cell(r, c).Range.Text = strText; } oTable.Rows[1].Range.Font.Bold = 1; oTable.Rows[1].Range.Font.Italic = 1; //接着添加一些文字 Microsoft.Office.Interop.Word.Paragraph oPara4; oRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; oPara4 = oDoc.Content.Paragraphs.Add(ref oRng); oPara4.Range.InsertParagraphBefore(); oPara4.Range.Text = "And here's another table:"; oPara4.Format.SpaceAfter = 24; oPara4.Range.InsertParagraphAfter(); //添加一个5行2列的表,填充数据并且改变列宽 wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; oTable = oDoc.Tables.Add(wrdRng, 5, 2, ref oMissing, ref oMissing); oTable.Range.ParagraphFormat.SpaceAfter = 6; for (r = 1; r <= 5; r++) for (c = 1; c <= 2; c++) { strText = "r" + r + "c" + c; oTable.Cell(r, c).Range.Text = strText; } oTable.Columns[1].Width = oWord.InchesToPoints(2); //设置列宽 oTable.Columns[2].Width = oWord.InchesToPoints(3); //Keep inserting text. When you get to 7 inches from top of the //document, insert a hard page break. object oPos; double dPos = oWord.InchesToPoints(7); oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range.InsertParagraphAfter(); do { wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; wrdRng.ParagraphFormat.SpaceAfter = 6; wrdRng.InsertAfter("A line of text"); wrdRng.InsertParagraphAfter(); oPos = wrdRng.get_Information (Microsoft.Office.Interop.Word.WdInformation.wdVerticalPositionRelativeToPage); } while (dPos >= Convert.ToDouble(oPos)); object oCollapseEnd = Microsoft.Office.Interop.Word.WdCollapseDirection.wdCollapseEnd; object oPageBreak = Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak; wrdRng.Collapse(ref oCollapseEnd); wrdRng.InsertBreak(ref oPageBreak); wrdRng.Collapse(ref oCollapseEnd); wrdRng.InsertAfter("We're now on page 2. Here's my chart:"); wrdRng.InsertParagraphAfter(); //添加一个chart Microsoft.Office.Interop.Word.InlineShape oShape; object oClassType = "MSGraph.Chart.8"; wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; oShape = wrdRng.InlineShapes.AddOLEObject(ref oClassType, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing); //Demonstrate use of late bound oChart and oChartApp objects to //manipulate the chart object with MSGraph. object oChart; object oChartApp; oChart = oShape.OLEFormat.Object; oChartApp = oChart.GetType().InvokeMember("Application", BindingFlags.GetProperty, null, oChart, null); //Change the chart type to Line. object[] Parameters = new Object[1]; Parameters[0] = 4; //xlLine = 4 oChart.GetType().InvokeMember("ChartType", BindingFlags.SetProperty, null, oChart, Parameters); //Update the chart image and quit MSGraph. oChartApp.GetType().InvokeMember("Update", BindingFlags.InvokeMethod, null, oChartApp, null); oChartApp.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, oChartApp, null); //... If desired, you can proceed from here using the Microsoft Graph //Object model on the oChart and oChartApp objects to make additional //changes to the chart. //Set the width of the chart. oShape.Width = oWord.InchesToPoints(6.25f); oShape.Height = oWord.InchesToPoints(3.57f); //Add text after the chart. wrdRng = oDoc.Bookmarks.get_Item(ref oEndOfDoc).Range; wrdRng.InsertParagraphAfter(); wrdRng.InsertAfter("THE END."); Console.ReadLine(); } } } |
2. 介绍几篇牛人写的关于操作Word的文章 [分享]一段导出到word模版的代码 http://www.cnblogs.com/goody9807/archive/2005/08/25/222526.html 再谈word2003编程 http://www.cnblogs.com/Andmm/archive/2008/06/18/1224422.html 最近一直在做C#操作office方面的工作!总结一下!Word(二) http://www.cnblogs.com/wngwz/archive/2004/08/19/34678.html C#也能动态生成Word文档并填充数据 http://www.cnblogs.com/qyfan82/archive/2007/09/14/893293.html from:http://www.cnblogs.com/tianzhiliang/archive/2011/07/07/2099800.html
View Details引用http://blog.csdn.net/mengyao/archive/2007/09/13/1784079.aspx using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using Microsoft.Office.Interop.Word; namespace WindowsApplication4 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { CreateWordFile("c:\\dd.doc"); } public string CreateWordFile(string CheckedInfo) { string message = ""; try { Object Nothing = System.Reflection.Missing.Value; Directory.CreateDirectory("C:/CNSI"); //创建文件所在目录 string name = "CNSI_" + DateTime.Now.ToLongDateString()+".doc"; object filename = "C://CNSI//" + name; //文件保存路径 //创建Word文档 Microsoft.Office.Interop.Word.Application WordApp = new Microsoft.Office.Interop.Word.ApplicationClass(); Microsoft.Office.Interop.Word.Document WordDoc = WordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing); //添加页眉 WordApp.ActiveWindow.View.Type = WdViewType.wdOutlineView; WordApp.ActiveWindow.View.SeekView = WdSeekView.wdSeekPrimaryHeader; WordApp.ActiveWindow.ActivePane.Selection.InsertAfter("[页眉内容]"); WordApp.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight;//设置右对齐 WordApp.ActiveWindow.View.SeekView = WdSeekView.wdSeekMainDocument;//跳出页眉设置 WordApp.Selection.ParagraphFormat.LineSpacing = 15f;//设置文档的行间距 //移动焦点并换行 object count = 14; object WdLine = Microsoft.Office.Interop.Word.WdUnits.wdLine;//换一行; WordApp.Selection.MoveDown(ref WdLine, ref count, ref Nothing);//移动焦点 WordApp.Selection.TypeParagraph();//插入段落 //文档中创建表格 Microsoft.Office.Interop.Word.Table newTable = WordDoc.Tables.Add(WordApp.Selection.Range, 12, 3, ref Nothing, ref Nothing); //设置表格样式 newTable.Borders.OutsideLineStyle = Microsoft.Office.Interop.Word.WdLineStyle.wdLineStyleThickThinLargeGap; newTable.Borders.InsideLineStyle = Microsoft.Office.Interop.Word.WdLineStyle.wdLineStyleSingle; newTable.Columns[1].Width = 100f; newTable.Columns[2].Width = 220f; newTable.Columns[3].Width = 105f; //填充表格内容 newTable.Cell(1, 1).Range.Text = "产品详细信息表"; newTable.Cell(1, 1).Range.Bold = 2;//设置单元格中字体为粗体 //合并单元格 newTable.Cell(1, 1).Merge(newTable.Cell(1, 3)); WordApp.Selection.Cells.VerticalAlignment = Microsoft.Office.Interop.Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter;//垂直居中 WordApp.Selection.ParagraphFormat.Alignment = Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphCenter;//水平居中 //填充表格内容 newTable.Cell(2, 1).Range.Text = "产品基本信息"; newTable.Cell(2, 1).Range.Font.Color = Microsoft.Office.Interop.Word.WdColor.wdColorDarkBlue;//设置单元格内字体颜色 //合并单元格 newTable.Cell(2, 1).Merge(newTable.Cell(2, 3)); WordApp.Selection.Cells.VerticalAlignment = Microsoft.Office.Interop.Word.WdCellVerticalAlignment.wdCellAlignVerticalCenter; //填充表格内容 newTable.Cell(3, 1).Range.Text = "品牌名称:"; newTable.Cell(3, 2).Range.Text = "BrandName"; //纵向合并单元格 newTable.Cell(3, 3).Select();//选中一行 object moveUnit = Microsoft.Office.Interop.Word.WdUnits.wdLine; object moveCount = 5; object moveExtend = Microsoft.Office.Interop.Word.WdMovementType.wdExtend; WordApp.Selection.MoveDown(ref moveUnit, ref moveCount, ref moveExtend); WordApp.Selection.Cells.Merge(); //插入图片 string FileName = @"c:\picture.jpg";//图片所在路径 object LinkToFile = false; object SaveWithDocument = true; object Anchor = WordDoc.Application.Selection.Range; WordDoc.Application.ActiveDocument.InlineShapes.AddPicture(FileName, ref LinkToFile, ref SaveWithDocument, ref Anchor); WordDoc.Application.ActiveDocument.InlineShapes[1].Width = 100f;//图片宽度 WordDoc.Application.ActiveDocument.InlineShapes[1].Height = 100f;//图片高度 //将图片设置为四周环绕型 Microsoft.Office.Interop.Word.Shape s = WordDoc.Application.ActiveDocument.InlineShapes[1].ConvertToShape(); […]
View Details一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = 0; Image img = Image.FromStream(ms); ms.Close(); this.pictureBox1.Image 二. C#中byte[]与string的转换代码 1、System.Text.UnicodeEncoding converter = new System.Text.UnicodeEncoding(); byte[] inputBytes =converter.GetBytes(inputString); string inputString = converter.GetString(inputBytes); 2、string inputString = System.Convert.ToBase64String(inputBytes); byte[] inputBytes = System.Convert.FromBase64String(inputString); FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); 三. C# Stream 和 byte[] 之间的转换 /// 将 Stream 转成 byte[] public byte[] StreamToBytes(Stream stream) { byte[] bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的位置为流的开始 stream.Seek(0, SeekOrigin.Begin); return bytes; } /// 将 byte[] 转成 Stream public Stream BytesToStream(byte[] bytes) { Stream stream = new […]
View Details|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
//直接方法重载+匿名对象 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); //构造路由然后添加 Route myroute = new Route("{controller}/{action}", new MvcRouteHandler()); routes.Add("MyRoute0", myroute); //跨命名空间路由 routes.MapRoute( "AddContollerRoute", "Home/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.AdditionalControllers" } ); routes.MapRoute( "MyRoute1", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "URLsAndRoutes.Controllers" } ); //可变长度路由 + 正则表达式匹配路由 routes.MapRoute( "MyRoute2", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*", action = "^Index$|^About$" }, new[] { "URLsAndRoutes.Controllers" } ); //指定请求方法 routes.MapRoute("MyRoute3", "{controller}/{action}/{id}/{*catchall}", new { controller = "Home", action = "Index", id = UrlParameter.Optional }, new { controller = "^H.*", action = "Index|About", httpMethod = new HttpMethodConstraint("GET") }, new[] { "URLsAndRoutes.Controllers" } ); |
先来看下面两个个url,对比一下: http://xxx.yyy.com/Admin/UserManager.aspx http://xxx.yyy.com/Admin/DeleteUser/1001 对于第1个Url,假设它与服务器上的文件有直接的关系,那么服务器在接受客户端请求并将对应的文件传送给客户端。我们大概可以猜到它是对用户管理的一个页面,它的物理文件UserManager.aspx在网站根目录下面的Admin文件夹中。而第2个url,在不知道Mvc路由以及Url重写时,很难猜到这个Url背后具体有些什么,前提条件是基于.Net框架开发的Web项目。 那么在这里,我们引入Asp.Net Mvc Url路由这个概念,也正是本文所要阐述的主题,Url路由模块是负责映射从浏览器请求到特定的控制器动作。 基于上面提到的Url路由以及其作用,我们就大概能猜到第2个Url背后有些啥了。 自然而然的Admin就是控制器了,DeleteUser是控制器里面的动作及Action了,1001就是Action的参数。到这里我们对Url路由有一个简单的认识,那么接着看下面一组url,假设Home是控制器,Index是控制器里面的Action,至于1001或者2345这类数据我们暂且约定为参数: http://xxx.yyy.com http://xxx.yyy.com/Home/1001 http://xxx.yyy.com/Index/1001 http://xxx.yyy.com/Home/Index/1001/2345 http://xxx.yyy.com/System/Home/Index/1001 按照约定,从上面的几组Url中可以看出,有的缺控制器,有的缺Action,有的带有好几个参数,有的又莫名的多出了控制器、Action、参数之外的东西,那么他们能正确的访问吗? 注册路由 在vs2012里面新建一个asp.net mvc4 web 应用程序项目,可以在项目的根目录下App_Start里面看到RouteConfig文件,在这个文件里面就可以添加url路由了。在文件里面可以看到MapRoute 这个方法,它是RouteCollection的扩展方法,并且含有多个重载,下面看看MapRoute方法的参数,这里选参数最多的那个:
|
1 |
|
1 |
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces); |
从上面的代码片段大概可以看出该方法含有路由名称、路由的Url、默认值、约束、首先查找路由所在的命名空间,该方法是返回对映射路由的引用。不过在RouteConfig文件中我们可以看到添加路由的代码:
|
1 |
|
1 2 3 4 5 |
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); |
稍微分析一下这段代码可以知道,在路由集合里面添加了一个名为"Default"的路由,并且有一个默认的路由指向,指向名称为Home的控制器,并且Action为Index,可以明显的看到这里 "id = UrlParameter.Optional" 的写法,它的意思就是说Action的参数可以不需要用户来指定,可以缺省。 多个参数如何传递 之前在一个QQ群里面见到一兄弟在问,类似这样的Url“http://xxx.yyy.com/Home/Index/1001/2345/tauruswu”在路由里面怎么配置?其实这个也很简单,我们只需要将路由配置、以及Action稍作调整。
|
1 |
|
1 2 3 4 5 |
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}/{*catchall}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); |
这个是调整之后的路由配置,只需要在Url后面再加上"{*catchall}"即可,那么Action调整之后如下
|
1 |
|
1 2 3 4 5 6 |
public ActionResult Index(string id,string catchall) { ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View(); } |
在Action里面定义了一个参数"catchall"用来接收Url中除了Id之外其他所有的参数值,那么上面那个Url中接收的参数就是“2345/tauruswu”,这样看起来好不好了,不过我觉得怪怪的,有没有更好的解决方法了?Url有必要写成那么长吗?这个问题在后续文章中会涉及到。 你也许会犯的错误 不知各位兄弟在刚刚接触MVC的时候,有没有碰到过这样的问题,如下图 那么这个错误是如何引起的了?代码是这么写的
|
1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
namespace MvcDebug.Controllers.Tauruswu { public class HomeController : Controller { public ActionResult Index(string id, string catchall) { ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View(); } } } |
我们再看英文提示大概就是说匹配出了多个控制器为"Home"的类型,在它的提示中也告诉了我们解决方法,说在MapRoute方法中使用"namespaces"这个参数,我们先将这个放在一边,将抛出这个错误的源码给找出来,具体的源码在DefaultControllerFactory这个类中,看类名就能猜出它的作用是什么了。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span style="font-family:'sans serif', tahoma, verdana, helvetica;line-height:1.5;"> <pre class="prettyprint lang-cs">private Type GetControllerTypeWithinNamespaces(RouteBase route, string controllerName, HashSet<string> namespaces) { // Once the master list of controllers has been created we can quickly index into it ControllerTypeCache.EnsureInitialized(BuildManager); ICollection<Type> matchingTypes = ControllerTypeCache.GetControllerTypes(controllerName, namespaces); switch (matchingTypes.Count) { case 0: // no matching types return null; case 1: // single matching type return matchingTypes.First(); default: // multiple matching types throw CreateAmbiguousControllerException(route, controllerName, matchingTypes); } } |
|
1 2 |
<span style="font-family:'sans serif', tahoma, verdana, helvetica;line-height:1.5;">上面粗体标出的代码,因为我们在路由中没有配置“namespaces”这个参数,这段代码的意思就是通过控制器名称获取所匹配的控制器类型集合,当获取到集合数据之后就开始Case了,很明显,这里集合的数目是2,自然就抛错了。 问题出来了,该如何解决?在错误提示中说要用到“namespaces”这个参数,我们能不能告诉MVC解析引擎,在解析控制器名称时,能不能对某些命名空间进行优先处理,事实上是可以的,只需要在配置路由的地方稍微调整一下</span> |
|
1 2 3 4 |
<pre class="prettyprint lang-cs">routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}/{*catchall}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, namespaces: new[] { "MvcDebug.Controllers.Tauruswu" } ); |
上面标粗的代码的意思是说优先解析“MvcDebug.Controllers.Tauruswu”这个命名空间里面的控制器。 路由约束 对于路由约束,我个人觉得这个可能在实际开发中用的不是很多,既然MapRoute方法提供了constraints这个参数及约束,那么在某些特定的场合肯定能发挥它的作用。在MVC中提供了三种路由约束方案,分别是: 1)正则表达式 ,2)http方法 ,3)自定义约束 。下面我们分别介绍下这三种约束的使用方法。 1)正则表达式 ,在路由配置中,我们做了这样的规则,只匹配Controller名称以H开头的
|
1 2 3 4 5 6 7 |
<pre class="prettyprint lang-cs">routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}/{*catchall}", defaults: new { controller = "Demo", action = "Index", id = UrlParameter.Optional }, constraints: new { controller = "^H.*" }, namespaces: new[] { "MvcDebug.Controllers.Tauruswu" } ); |
2) http方法 ,我们将路由配置稍作修改
|
1 2 3 4 5 6 7 |
<pre class="prettyprint lang-cs">routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}/{*catchall}", defaults: new { controller = "Demo", action = "Index", id = UrlParameter.Optional }, constraints: new { httpMethod = new HttpMethodConstraint("POST"), }, namespaces: new[] { "MvcDebug.Controllers.Tauruswu" } ); |
然后在对应的Action上面打个标记
|
1 2 3 4 5 6 7 |
<pre class="prettyprint lang-cs">[HttpGet] public ActionResult Index() { ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。"; return View(); } |
你们说这样行不行了? 3) 自定义约束,如果说上面两种需求还是不能满足你,那么我们可以自定义约束。我们翻看HttpMethodConstraint这个类,可以看到它是继承IRouteConstraint这个接口,其定义是
|
1 2 3 4 |
<pre class="prettyprint lang-cs">public interface IRouteConstraint { bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection); } |
里面只有一个布尔类型的方法,关于这个例子,是从网上借鉴过来的,如下
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<pre class="prettyprint lang-cs">public class CustomConstraint : IRouteConstraint { private string requiredAgent; public CustomConstraint(string agentArgs) { this.requiredAgent = agentArgs; } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { return httpContext.Request.UserAgent != null && httpContext.Request.UserAgent.Contains(requiredAgent); } } |
这段代码的意思就是检查客户端请求的UserAgent属性值,看它是否含有一个被传递给构造函数的值。那么我们将路由作如下修改
|
1 2 3 4 5 6 7 |
<pre class="prettyprint lang-cs">routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}/{*catchall}", defaults: new { controller = "Demo", action = "Index", id = UrlParameter.Optional }, constraints: new { customConstraint = new CustomConstraint("IE"), }, namespaces: new[] { "MvcDebug.Controllers.Tauruswu" } ); |
很显然,这个只能在IE游览器下面游览。 如何创建自定义路由处理程序 在翻阅MapRoute方法源码的时候,看到了这么一段
|
1 2 3 4 5 6 7 8 9 |
<pre class="prettyprint lang-cs">Route route = new Route(url, new MvcRouteHandler()) { Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() }; ..... routes.Add(name, route); |
在Route实例化的时候,它是用到了“MvcRouteHandler“这个类,该类继承”IRouteHandler“接口,如果我们不用系统里面已经定义好的路由处理方案,我们要自己来实现一套?改怎么下手,此时只需要继承”IRouteHandler“这个接口并实现”GetHttpHandler“方法即可。 最后在添加路由时,像这样操作
|
1 |
routes.Add(new Route("DemoUrl",new DemoRouteHandler()); |
当我们在游览器里面请求/DemoUrl这个地址时,就会用到我们自定义的处理程序,在实际开发当中,如果真的要用到自定义路由处理程序,那么我们就要实现很多原本框架所实现的空能,虽然这给我们带来了很大的扩展空间,但是又不可控。 总结 Url路由系统是通过请求地址进行解析从而得到以目标Controller/Action名称为核心的路由数据,Url路由系统是建立在Asp.net 之上,我们在调试System.Web.Routing的源码时候可以得知。在这里我们由浅入深的了解了路由系统,接下来我们会讲到控制器以及Action,也是最为核心的东西。 转发处:http://www.cnblogs.com/wucj/p/3113878.html
View Details之前还以为从上至下统一用上UTF-8就高枕无忧了,哪知道今天在抓取新浪微博的数据的时候还是遇到字符的异常。 从新浪微博抓到的数据在入库的时候抛出异常: Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90…' 发现导致异常的字符不是繁体而是某种佛经文字。。。额滴神。。。但是按道理UTF-8应该能支持才对啊,他不是万能的么? 原来问题出在mysql上,mysql如果设置编码集为utf8那么它最多只能支持到3个字节的UTF-8编码,而4个字节的UTF-8字符还是存在的,这样一来如果你建表的时候用的utf8字符集出异常就理所当然了。 解决方法很简单,修改字段或者表的字符集为utf8mb4。 比较蛋疼的是,字符集utf8mb4在mysql 5.5.3之后才支持。。。 [2015.03.30]更新: 事实证明只做上面的步骤是无法解决问题的,如果需要解决请参考:http://info.michael-simons.eu/2013/01/21/java-mysql-and-multi-byte-utf-8-support/ 明天要研究如何升级mysql了。。。 参考: http://stackoverflow.com/questions/10957238/incorrect-string-value-when-trying-to-insert-utf-8-into-mysql-via-jdbc http://topic.csdn.net/u/20091107/17/c0eb2463-b4bb-4197-bd67-0459db8aa137.html from:http://blog.csdn.net/shootyou/article/details/8236024
View Details