
暂无个人介绍
根据SNS Research最新报告显示,到2020年,授权3GPP技术将占所有低功率广域(LPWA)网络连接的35%以上。 在智能测量、照明控制和停车管理等物联网应用中非常受欢迎的LPWA网络,预计将对M2M和IoT生态系统做出重大贡献,到2020年,服务收入估计将达到230亿美元。 目前,大多数LPWA网络都是基于专有技术,并且运行于免许可频谱,主要在Sub-GHz(即频率为1GHz以下,27MHz~960 MHz)频段。 然而,随着3GPP最近完成了NB-IoT、LTECat-M1和EC-GSM-IoT标准,移动运营商积开始积极进行软件升级以构建自己的运营商级LPWA网络。 本文转自d1net(转载)
随着云计算、大数据、移动化日趋流行,基于此类技术衍生的产品也被越来越广泛的应用于工作场景,并潜移默化地改变着我们的工作方式。异地协作、手机审批、智能助理逐渐被企业所采纳,这不仅降低了传统的企业管理和运营成本,还能有效提高工作效率,让企业从容应对日新月异的技术变革。目前市场上,企业级应用软件种类繁多,但数据管理协同、企业协作沟通以及销售管理应用可谓是基础必备级。 数据管理协同:联想企业网盘 任何企业的运行离不开数据,无论是数据的存储、编辑还是分享,都每天在企业上演。随着数据存储容量累增以及企业规模扩大,传统的数据管理模式已无法很好地满足企业需求,取而代之,基于云计算的云存储系统则成为了首选的数据管理平台。 目前占据最大市场份额的企业级云盘为联想企业网盘,与其他所有云存储产品一样,它提供基础的文件集中存储、归档、管理以及协同功能,可支持异地协同及移动办公。但其在文件传输速度以及分配管理权限上具有独特优势。在文件传输速度上,以100MB左右的文件为例,它的传输速度可快至1分30秒左右。文件上传至网盘后,还可一键生成外链进行发送,提高了办公效率。在管理权限上,该网盘可针对不同人员和职责,赋予预览、下载、编辑、重命名等多种不同权限组合,非常适合组织结构复杂且对文件安全性要求高的企业使用。 企业协作沟通:钉钉 由传统的电话到后来的实时通讯工具,企业对内对外的沟通方式越来越多样化,但企业始终在寻找一种低成本且高效率的沟通工具。近几年,IM社交市场不断增长且被更多的运用于职场中,在个人IM领域,微信可以说是一家独大,但在企业级IM领域,市场格局仍然在形成中。 在企业级IM领域,依托于阿里巴巴的明星光环, 钉钉自诞生以来一直较博人眼球。钉钉为一款智能移动办公软件,支持统一通讯录、沟通、智能电话以及移动办公。在沟通方面,钉钉具有视频电话会议、商务电话、短信信息等功能,集合了多种沟通工具的功能。此外,钉钉还支持协同办公,比如拥有请假,报销,出差等常用流程审批,通过与其基础的通信能力相结合,将各种办公审批快速以短信或电话通知对方。钉钉前不久推出了3.0产品,还新增了办公电话以及外部联系人的功能,能更好地解决掌握客户资源人员的流动所带来的问题。对于有强烈的移动办公需求,同时又追求成本效益的企业来说,钉钉提供了一种更灵活更智能的办公新方式。 企业销售管理:销售易 企业管理过程中,企业尤为重视对直接关系到营业额的销售业绩的管理,这也是为什么在SaaS产品中,专注销售管理的CRM产品一直热门的原因。CRM产品不仅投入成本低,同时可支持销售人员移动办公和及时反馈一线销售信息,是现代企业的创新销售神器。 在此领域,销售易素有中国的Salesforce之称,并在市场享有较高的占有率。其近期上线的CRM4.4产品还集成了呼叫中心系统,可实现来电弹屏提醒、一键拨打电话、三方通话和呼叫转移功能,帮助企业搭建高效的电销团队以及以客户为中心的销售和服务流程。同时,新产品还升级了回款管理功能,让销售根据实际业务需求,灵活创建自定义的回款计划内容和布局,并可通过移动端随时录入收款计划,并设置回款逾期自动提醒和进行报表实时统计。对于移动互联时代的销售管理,销售易提供了一套全流程自动化的CRM管理解决方案。 以上三款SaaS级产品,将从数据管理、沟通协作以及销售管理方面助力现代企业减负增效。随着云计算、大数据以及移动化等技术不断渗透,传统的办公方式将迎来变革,拥抱变革的企业将迎来更多新的机遇。 本文转自d1net(转载)
大数据是一个含义广泛的术语,是指数据集,如此庞大而复杂的,他们需要专门设计的硬件和软件工具进行处理。该数据集通常是万亿或EB的大小。这些数据集收集自各种各样的来源:传感器,气候信息,公开的信息,如杂志,报纸,文章。大数据产生的其他例子包括购买交易记录,网络日志,病历,军事监控,视频和图像档案,及大型电子商务。 在大数据和大数据分析,他们对企业的影响有一个兴趣高涨。大数据分析是研究大量的数据的过程中寻找模式,相关性和其他有用的信息,可以帮助企业更好地适应变化,并做出更明智的决策。 一、Hadoop Hadoop 是一个能够对大量数据进行分布式处理的软件框架。但是 Hadoop 是以一种可靠、高效、可伸缩的方式进行处理的。Hadoop 是可靠的,因为它假设计算元素和存储会失败,因此它维护多个工作数据副本,确保能够针对失败的节点重新分布处理。Hadoop 是高效的,因为它以并行的方式工作,通过并行处理加快处理速度。Hadoop 还是可伸缩的,能够处理 PB 级数据。此外,Hadoop 依赖于社区服务器,因此它的成本比较低,任何人都可以使用。 Hadoop是一个能够让用户轻松架构和使用的分布式计算平台。用户可以轻松地在Hadoop上开发和运行处理海量数据的应用程序。它主要有以下几个优点: ⒈高可靠性。Hadoop按位存储和处理数据的能力值得人们信赖。 ⒉高扩展性。Hadoop是在可用的计算机集簇间分配数据并完成计算任务的,这些集簇可以方便地扩展到数以千计的节点中。 ⒊高效性。Hadoop能够在节点之间动态地移动数据,并保证各个节点的动态平衡,因此处理速度非常快。 ⒋高容错性。Hadoop能够自动保存数据的多个副本,并且能够自动将失败的任务重新分配。 Hadoop带有用 Java 语言编写的框架,因此运行在 Linux 生产平台上是非常理想的。Hadoop 上的应用程序也可以使用其他语言编写,比如 C++。 二、HPCC HPCC,High Performance Computing and Communications(高性能计算与通信)的缩写。1993年,由美国科学、工程、技术联邦协调理事会向国会提交了“重大挑战项目:高性能计算与 通信”的报告,也就是被称为HPCC计划的报告,即美国总统科学战略项目,其目的是通过加强研究与开发解决一批重要的科学与技术挑战问题。HPCC是美国 实施信息高速公路而上实施的计划,该计划的实施将耗资百亿美元,其主要目标要达到:开发可扩展的计算系统及相关软件,以支持太位级网络传输性能,开发千兆 比特网络技术,扩展研究和教育机构及网络连接能力。 该项目主要由五部分组成: 1、高性能计算机系统(HPCS),内容包括今后几代计算机系统的研究、系统设计工具、先进的典型系统及原有系统的评价等; 2、先进软件技术与算法(ASTA),内容有巨大挑战问题的软件支撑、新算法设计、软件分支与工具、计算计算及高性能计算研究中心等; 3、国家科研与教育网格(NREN),内容有中接站及10亿位级传输的研究与开发; 4、基本研究与人类资源(BRHR),内容有基础研究、培训、教育及课程教材,被设计通过奖励调查者-开始的,长期 的调查在可升级的高性能计算中来增加创新意识流,通过提高教育和高性能的计算训练和通信来加大熟练的和训练有素的人员的联营,和来提供必需的基础架构来支 持这些调查和研究活动; 5、信息基础结构技术和应用(IITA ),目的在于保证美国在先进信息技术开发方面的领先地位。 三、Storm Storm是自由的开源软件,一个分布式的、容错的实时计算系统。Storm可以非常可靠的处理庞大的数据流,用于处理Hadoop的批量数据。Storm很简单,支持许多种编程语言,使用起来非常有趣。Storm由Twitter开源而来,其它知名的应用企业包括Groupon、淘宝、支付宝、阿里巴巴、乐元素、 Admaster等等。 Storm有许多应用领域:实时分析、在线机器学习、不停顿的计算、分布式RPC(远过程调用协议,一种通过网络从远程计算机程序上请求服务)、 ETL(Extraction-Transformation-Loading的缩写,即数据抽取、转换和加载)等等。Storm的处理速度惊人:经测 试,每个节点每秒钟可以处理100万个数据元组。Storm是可扩展、容错,很容易设置和操作。 四、Apache Drill 为了帮助企业用户寻找更为有效、加快Hadoop数据查询的方法,Apache软件基金会近日发起了一项名为“Drill”的开源项目。Apache Drill 实现了 Google’s Dremel. 据Hadoop厂商MapR Technologies公司产品经理Tomer Shiran介绍,“Drill”已经作为Apache孵化器项目来运作,将面向全球软件工程师持续推广。 该项目将会创建出开源版本的谷歌Dremel Hadoop工具(谷歌使用该工具来为Hadoop数据分析工具的互联网应用提速)。而“Drill”将有助于Hadoop用户实现更快查询海量数据集的目的。 “Drill”项目其实也是从谷歌的Dremel项目中获得灵感:该项目帮助谷歌实现海量数据集的分析处理,包括分析抓取Web文档、跟踪安装在Android Market上的应用程序数据、分析垃圾邮件、分析谷歌分布式构建系统上的测试结果等等。 通过开发“Drill”Apache开源项目,组织机构将有望建立Drill所属的API接口和灵活强大的体系架构,从而帮助支持广泛的数据源、数据格式和查询语言。 五、RapidMiner RapidMiner是世界领先的数据挖掘解决方案,在一个非常大的程度上有着先进技术。它数据挖掘任务涉及范围广泛,包括各种数据艺术,能简化数据挖掘过程的设计和评价。 功能和特点 免费提供数据挖掘技术和库 100%用Java代码(可运行在操作系统) 数据挖掘过程简单,强大和直观 内部XML保证了标准化的格式来表示交换数据挖掘过程 可以用简单脚本语言自动进行大规模进程 多层次的数据视图,确保有效和透明的数据 图形用户界面的互动原型 命令行(批处理模式)自动大规模应用 Java API(应用编程接口) 简单的插件和推广机制 强大的可视化引擎,许多尖端的高维数据的可视化建模 400多个数据挖掘运营商支持 耶鲁大学已成功地应用在许多不同的应用领域,包括文本挖掘,多媒体挖掘,功能设计,数据流挖掘,集成开发的方法和分布式数据挖掘。 六、 Pentaho BI Pentaho BI 平台不同于传统的BI 产品,它是一个以流程为中心的,面向解决方案(Solution)的框架。其目的在于将一系列企业级BI产品、开源软件、API等等组件集成起来,方便商务智能应用的开发。它的出现,使得一系列的面向商务智能的独立产品如Jfree、Quartz等等,能够集成在一起,构成一项项复杂的、完整的商务智能解决方案。 Pentaho BI 平台,Pentaho Open BI 套件的核心架构和基础,是以流程为中心的,因为其中枢控制器是一个工作流引擎。工作流引擎使用流程定义来定义在BI 平台上执行的商业智能流程。流程可以很容易的被定制,也可以添加新的流程。BI 平台包含组件和报表,用以分析这些流程的性能。目前,Pentaho的主要组成元素包括报表生成、分析、数据挖掘和工作流管理等等。这些组件通过 J2EE、WebService、SOAP、HTTP、Java、JavaScript、Portals等技术集成到Pentaho平台中来。 Pentaho的发行,主要以Pentaho SDK的形式进行。 Pentaho SDK共包含五个部分:Pentaho平台、Pentaho示例数据库、可独立运行的Pentaho平台、Pentaho解决方案示例和一个预先配制好的 Pentaho网络服务器。其中Pentaho平台是Pentaho平台最主要的部分,囊括了Pentaho平台源代码的主体;Pentaho数据库为 Pentaho平台的正常运行提供的数据服务,包括配置信息、Solution相关的信息等等,对于Pentaho平台来说它不是必须的,通过配置是可以用其它数据库服务取代的;可独立运行的Pentaho平台是Pentaho平台的独立运行模式的示例,它演示了如何使Pentaho平台在没有应用服务器支持的情况下独立运行;Pentaho解决方案示例是一个Eclipse工程,用来演示如何为Pentaho平台开发相关的商业智能解决方案。 Pentaho BI 平台构建于服务器,引擎和组件的基础之上。这些提供了系统的J2EE 服务器,安全,portal,工作流,规则引擎,图表,协作,内容管理,数据集成,分析和建模功能。这些组件的大部分是基于标准的,可使用其他产品替换之。 本文转自d1net(转载)
Mono的更新速度加快,经常需要升级系统里面的Mono版本。Mono可以使用源码安装和rpm包安装2种方式,对应的升级方法也有2种。 1、如果旧版本是用 rpm装的,那么请用rpm命令删除,通常不同的发行版的命令不一样,例如Ubuntu使用apt-get removoe mono,OpenSuse上使用的zypper remove mono,然后用最新版的源文件安装。 2、如果旧版本是用源文件编译安装的,并且保存了安装的源文件夹,那么就用 make uninstall 卸载,然后安装新版本,如果你的源安装文件夹没有保存,那么就覆盖安装,但必须找到原来安装的目录文件夹,比如,默认安装的目标文件夹是 /usr/local 那么,你在新安装时就要用这个文件夹,这样才能覆盖掉就版本的mono. 根据经验,建议要把mono安装到 /usr中,不建议按默认目标文件夹安装。如果要用新的文件夹安装,也必须找准你过去的安装路径,简单的办法是看mono这个可执行文件在哪个文件夹,找到后,删除mono这个主要的可执行文件,当然,也尽量手工删除与mono有关的文件,比如mcs,gmcs,smcs等(其它相关文件删不完无所谓)。然后安装新版。用 ./confingure --prefix=/usr 明确指定目标文件夹。另外一个要点,是,要用root身份安装,以保证mono拥有足够的运行权限。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Spacebuilder 是一个asp.net mvc3项目,使用到了Combres,Combres依赖于dotless,然后在Spacebuilder的项目没有见到的dotless,运行要求dotless 1.3.0.2版本,通过Nuget获取: Install-Package dotless -Version 1.3.0.2 修改web.config加入dotless配置: <configuration> <configSections> <section name="combres" requirePermission="false" type="Combres.ConfigSectionSetting, Combres, Version=2.2.2.6" /> <section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler, dotless.Core" /> </configSections> …… <dotless minifyCss="false" cache="true" web="false" /> </configuration> 另外将Microsoft.Web.Infrastructure.dll 剔除,让程序使用Mono自带的动态库,具体参看 Linux.NET学习手记(5)或者 Get MVC3 Razor Running on Mono。 访问 http://mono.cloudapp.net/ ,接着又发生了数据库连接错误:System.NotImplementedException (SSL encryption for data sent between client and server is not implemented.)在stackoverflow上看到了类似问题:http://stackoverflow.com/questions/14075667/cant-connect-to-sql-azure-database-using-monotouch,看来通过Windows Azure来做测试没戏,还得老实搭建本地环境来测试。 在Windows Azure独立建立一个虚拟机安装SQL Server 2008 R2,手工安装spb。 System.InvalidProgramException Invalid IL code in System.Web.Handlers.ScriptModule:.ctor (): method body is empty. Description: HTTP 500.Error processing request. Details: Non-web exception. Exception origin (name of application or object): mscorlib. Exception stack trace: at (wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&) at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <filename unknown>:0 需要使用mono版本的System.Web.Extensions.dll,System.Web.WebPages.Administration.dll}}U6{Y~IX~GAI2W~([T]NZM 在Mono 下以上程序集就可以跑ASP.NET mvc 3. web.config 添加上了 <globalization culture="zh-CN" uiCulture="en-US"/> 但还是报错 System.ArgumentNullException Argument cannot be null. Parameter name: key Description: HTTP 500.Error processing request. Details: Non-web exception. Exception origin (name of application or object): mscorlib. Exception stack trace: at System.Resources.ResourceManager.InternalGetResourceSet (System.Globalization.CultureInfo culture, Boolean createIfNotExists, Boolean tryParents) [0x00000] in <filename unknown>:0 at System.Resources.ResourceManager.InternalGetResourceSet (System.Globalization.CultureInfo culture, Boolean createIfNotExists, Boolean tryParents) [0x00000] in <filename unknown>:0 at System.Resources.ResourceManager.InternalGetResourceSet (System.Globalization.CultureInfo culture, Boolean createIfNotExists, Boolean tryParents) [0x00000] in <filename unknown>:0 at System.Resources.ResourceManager.GetString (System.String name, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0 at System.Web.Razor.Resources.RazorResources.get_BlockName_Code () [0x00000] in <filename unknown>:0 at System.Web.Razor.Parser.CSharpCodeParser.ParseBlock () [0x00000] in <filename unknown>:0 at System.Web.Razor.Parser.ParserBase.ParseBlockWithOtherParser (System.Web.Razor.Parser.SyntaxTree.SpanFactory previousSpanFactory, Boolean collectTransitionToken) [0x00000] in <filename unknown>:0 at System.Web.Razor.Parser.HtmlMarkupParser.TryStartCodeParser (Boolean isSingleLineMarkup, Boolean documentLevel) [0x00000] in <filename unknown>:0 at System.Web.Razor.Parser.HtmlMarkupParser.ParseRootBlock (System.Tuple`2 nestingSequences, Boolean caseSensitive) [0x00000] in <filename unknown>:0 at System.Web.Razor.Parser.HtmlMarkupParser.ParseDocument () [0x00000] in <filename unknown>:0 at System.Web.Razor.Parser.RazorParser.Parse (System.Web.Razor.Text.LookaheadTextReader input, System.Web.Razor.Parser.ParserVisitor visitor) [0x00000] in <filename unknown>:0 at System.Web.Razor.RazorTemplateEngine.GenerateCodeCore (System.Web.Razor.Text.LookaheadTextReader input, System.String className, System.String rootNamespace, System.String sourceFileName, Nullable`1 cancelToken) [0x00000] in <filename unknown>:0 at System.Web.Razor.RazorTemplateEngine.GenerateCode (System.IO.TextReader input, System.String className, System.String rootNamespace, System.String sourceFileName, Nullable`1 cancelToken) [0x00000] in <filename unknown>:0 at System.Web.Razor.RazorTemplateEngine.GenerateCode (System.IO.TextReader input, System.String className, System.String rootNamespace, System.String sourceFileName) [0x00000] in <filename unknown>:0 at System.Web.WebPages.Razor.RazorBuildProvider.EnsureGeneratedCode () [0x00000] in <filename unknown>:0 at System.Web.WebPages.Razor.RazorBuildProvider.get_CodeCompilerType () [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManagerDirectoryBuilder.GetBuildProviderCodeDomType (System.Web.Compilation.BuildProvider bp) [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManagerDirectoryBuilder.AssignToGroup (System.Web.Compilation.BuildProvider buildProvider, System.Collections.Generic.List`1 groups) [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManagerDirectoryBuilder.Build (Boolean single) [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManager.BuildInner (System.Web.VirtualPath vp, Boolean debug) [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManager.Build (System.Web.VirtualPath vp) [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManager.GetCompiledType (System.Web.VirtualPath virtualPath) [0x00000] in <filename unknown>:0 at System.Web.Compilation.BuildManager.GetCompiledType (System.String virtualPath) [0x00000] in <filename unknown>:0 at System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.GetCompiledType (System.String virtualPath) [0x00000] in <filename unknown>:0 at System.Web.Mvc.BuildManagerCompiledView.Render (System.Web.Mvc.ViewContext viewContext, System.IO.TextWriter writer) [0x00000] in <filename unknown>:0 at System.Web.Mvc.ViewResultBase.ExecuteResult (System.Web.Mvc.ControllerContext context) [0x00000] in <filename unknown>:0 at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult (System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ActionResult actionResult) [0x00000] in <filename unknown>:0 at System.Web.Mvc.ControllerActionInvoker+<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19 () [0x00000] in <filename unknown>:0 at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter (IResultFilter filter, System.Web.Mvc.ResultExecutingContext preContext, System.Func`1 Running Mono 3.2.0 with .NET MVC 4 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
之前整理过一篇文章《zookeeper 分布式锁服务》,本文介绍的 Zookeeper 是以 3.4.5 这个稳定版本为基础,最新的版本可以通过官网 http://hadoop.apache.org/zookeeper/来获取,Zookeeper 的安装非常简单,下面将从单机模式和集群模式两个方面介绍 Zookeeper 的Windows安装和配置. 首先需要安装JdK,从Oracle的Java网站下载,安装很简单,就不再详述。 单机模式 单机安装非常简单,只要获取到 Zookeeper 的压缩包并解压到某个目录如:C:zookeeper-3.4.5下,Zookeeper 的启动脚本在 bin 目录下,Windows 下的启动脚本是 zkServer.cmd。 在你执行启动脚本之前,还有几个基本的配置项需要配置一下,Zookeeper 的配置文件在 conf 目录下,这个目录下有 zoo_sample.cfg 和 log4j.properties,你需要做的就是将 zoo_sample.cfg 改名为 zoo.cfg,因为 Zookeeper 在启动时会找这个文件作为默认配置文件。下面详细介绍一下,这个配置文件中各个配置项的意义。 # The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement syncLimit=5 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. dataDir=C:\\zookeeper-3.4.5\\data dataLogDir=C:\\zookeeper-3.4.5\\log # the port at which the clients will connect clientPort=2181 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1 tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。dataLogDir:顾名思义就是 Zookeeper 保存日志文件的目录clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。当这些配置项配置好后,你现在就可以启动 Zookeeper 了,启动后要检查 Zookeeper 是否已经在服务,可以通过 netstat – ano 命令查看是否有你配置的 clientPort 端口号在监听服务。 集群模式 Zookeeper 不仅可以单机提供服务,同时也支持多机组成集群来提供服务。实际上 Zookeeper 还支持另外一种伪集群的方式,也就是可以在一台物理机上运行多个 Zookeeper 实例,下面将介绍集群模式的安装和配置。 Zookeeper 的集群模式的安装和配置也不是很复杂,所要做的就是增加几个配置项。集群模式除了上面的三个配置项还要增加下面几个配置项: initLimit=5 syncLimit=2 server.1=192.168.211.1:2888:3888 server.2=192.168.211.2:2888:3888 initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。除了修改 zoo.cfg 配置文件,集群模式下还要配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面就有一个数据就是 A 的值,Zookeeper 启动时会读取这个文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是那个 server。数据模型 Zookeeper 会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统,如图 1 所示: zookeeperZookeeper 这种数据结构有如下这些特点:每个子目录项如 NameService 都被称作为 znode,这个 znode 是被它所在的路径唯一标识,如 Server1 这个 znode 的标识为 /NameService/Server1znode 可以有子节点目录,并且每个 znode 可以存储数据,注意 EPHEMERAL 类型的目录节点不能有子节点目录znode 是有版本的,每个 znode 中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据znode 可以是临时节点,一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为 session,如果 znode 是临时节点,这个 session 失效,znode 也就删除了znode 的目录名可以自动编号,如 App1 已经存在,再创建的话,将会自动命名为 App2znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于这个特性实现的,后面在典型的应用场景中会有实例介绍如何使用 Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理. 通过C#代码使用zookeeper Zookeeper的使用主要是通过创建其Nuget ZooKeeperNet包下的Zookeeper实例,并且调用其接口方法进行的,主要的操作就是对znode的增删改操作,监听znode的变化以及处理。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ZooKeeperNet; namespace ZookeeperDemo { class Watcher : IWatcher { public void Process(WatchedEvent @event) { if (@event.Type == EventType.NodeDataChanged) { Console.WriteLine(@event.Path); } } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using ZooKeeperNet; namespace ZookeeperDemo { class Program { static void Main(string[] args) { //创建一个Zookeeper实例,第一个参数为目标服务器地址和端口,第二个参数为Session超时时间,第三个为节点变化时的回调方法 using (ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", new TimeSpan(0, 0, 0, 50000), new Watcher())) { var stat = zk.Exists("/root",true); ////创建一个节点root,数据是mydata,不进行ACL权限控制,节点为永久性的(即客户端shutdown了也不会消失) //zk.Create("/root", "mydata".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent); //在root下面创建一个childone znode,数据为childone,不进行ACL权限控制,节点为永久性的 zk.Create("/root/childone", "childone".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent); //取得/root节点下的子节点名称,返回List<String> zk.GetChildren("/root", true); //取得/root/childone节点下的数据,返回byte[] zk.GetData("/root/childone", true, null); //修改节点/root/childone下的数据,第三个参数为版本,如果是-1,那会无视被修改的数据版本,直接改掉 zk.SetData("/root/childone", "childonemodify".GetBytes(), -1); //删除/root/childone这个节点,第二个参数为版本,-1的话直接删除,无视版本 zk.Delete("/root/childone", -1); } } } } 浅析 创建连接: 1.获取服务主机列表 2.设置超时时间 3.注册客户端事件 4.以线程安全的方式创建请求连接(启动客户端请求队列,循环队列基于socket通信、根据请求类型执行不同的请求动作) 请求流程: 构造请求头、构造request,reponse、构造响应头、构造Packet对象,packet对象准备好后,把整个对象放入一个outgoingQueue packet被放入outgoingQueue中,等待SendThread把packet对应的内容发送给server。server处理分3步在doio方法中ReadLength ReadConnectResult ReadResponse,直到ReadResponse方法中确定packet请求结束。 响应流程: 针对心跳的ping请求的resp,针对auth请求的resp,一般接口请求的resp,如果接口请求要求了watcher,当watcher关注的内容有变化时的notification 锁相关部分API方法: 创建节点:create demo:zk.Create(Dir, severname.GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Persistent); 其中CreateMode分为4类Persistent、PersistentSequential、Ephemeral、EphemeralSequential PERSISTENT 创建持久化节点,对应机器关闭连接后节点/数据不会消失 PERSISTENT_SEQUENTIAL 如果PATH是以’/’结尾则以这个PATH作为父节点,创建一个子节点,其子节点名字是一个按先后顺序排列的数值;否则创建一个名字是‘/’后面字符加上先后顺序排列的数值字符串的节点,同样创建持久节点 EPHEMERAL 创建瞬时节点,Zookeeper在感知连接机器宕机后会清除它创建的瞬时节点 EPHEMERAL_SEQUENTIAL 穿件瞬时顺序节点,和PERSISTENT_SEQUENTIAL一样,区别在于它是瞬时的 删除节点 delete demo :zk.Delete(Dir, -1); 前一个参数代表节点名称(一般用作路径),后一个是版本号 -1表示全匹配 查看节点 exists demo : zk.Exists(Dir, new MyWatch2()); 获取数据 getData demo :zk.GetData(Dir, new MyWatch2(), stat); 获取一个节点的数据,可注入watcher 设置数据 setData demo : zk.SetData(Dir, new byte[1], 1); 获取下级节点集合 GetChildren demo :zk.GetChildren(Dir, true); 存储 znodes类似文件和目录。但它不是一个典型的文件系统,zookeeper数据保存在内存中,这意味着zookeeper可以实现高吞吐量和低延迟。 watcher Zookeeper有两种watches,一种是data watches,另一种是child watches。其中,getData()和exists()以及create()等会添加data watches,getChildren()会添加child watches。而delete()涉及到删除数据和子节点,会同时触发data watches和child watches。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
一、 PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃、断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统库是MyISAM的,相比之下,PG数据库这方面要好一些。二、任何系统都有它的性能极限,在高并发读写,负载逼近极限下,PG的性能指标仍可以维持双曲线甚至对数曲线,到顶峰之后不再下降,而 MySQL 明显出现一个波峰后下滑(5.5版本之后,在企业级版本中有个插件可以改善很多,不过需要付费)。三、PG 多年来在 GIS 领域处于优势地位,因为它有丰富的几何类型,实际上不止几何类型,PG有大量字典、数组、bitmap 等数据类型,相比之下mysql就差很多,instagram就是因为PG的空间数据库扩展POSTGIS远远强于MYSQL的my spatial而采用PGSQL的。 四、PG 的“无锁定”特性非常突出,甚至包括 vacuum 这样的整理数据空间的操作,这个和PGSQL的MVCC实现有关系。五、PG 的可以使用函数和条件索引,这使得PG数据库的调优非常灵活,mysql就没有这个功能,条件索引在web应用中很重要。六、PG有极其强悍的 SQL 编程能力(9.x 图灵完备,支持递归!),有非常丰富的统计函数和统计语法支持,比如分析函数(ORACLE的叫法,PG里叫window函数),还可以用多种语言来写存储过程,对于R的支持也很好。这一点上MYSQL就差的很远,很多分析功能都不支持,腾讯内部数据存储主要是MYSQL,但是数据分析主要是HADOOP+PGSQL。七、PG 的有多种集群架构可以选择,plproxy 可以支持语句级的镜像或分片,slony 可以进行字段级的同步设置,standby 可以构建WAL文件级或流式的读写分离集群,同步频率和集群策略调整方便,操作非常简单。八、一般关系型数据库的字符串有限定长度8k左右,无限长 TEXT 类型的功能受限,只能作为外部大数据访问。而 PG 的 TEXT 类型可以直接访问,SQL语法内置正则表达式,可以索引,还可以全文检索,或使用xml xpath。用PG的话,文档数据库都可以省了。九,对于WEB应用来说,复制的特性很重要,mysql到现在也是异步复制,pgsql可以做到同步,异步,半同步复制。还有mysql的同步是基于binlog复制,类似oracle golden gate,是基于stream的复制,做到同步很困难,这种方式更加适合异地复制,pgsql的复制基于wal,可以做到同步复制。同时,pgsql还提供stream复制。十,pgsql对于numa架构的支持比mysql强一些,比MYSQL对于读的性能更好一些,pgsql提交可以完全异步,而mysql的内存表不够实用(因为表锁的原因) 最后说一下我感觉 PG 不如 MySQL 的地方。第一,MySQL有一些实用的运维支持,如 slow-query.log ,这个pg肯定可以定制出来,但是如果可以配置使用就更好了。第二是mysql的innodb引擎,可以充分优化利用系统所有内存,超大内存下PG对内存使用的不那么充分,第三点,MySQL的复制可以用多级从库,但是在9.2之前,PGSQL不能用从库带从库。第四点,从测试结果上看,mysql 5.5的性能提升很大,单机性能强于pgsql,5.6应该会强更多.第五点,对于web应用来说,mysql 5.6 的内置MC API功能很好用,PGSQL差一些。 另外一些:pgsql和mysql都是背后有商业公司,而且都不是一个公司。大部分开发者,都是拿工资的。说mysql的执行速度比pgsql快很多是不对的,速度接近,而且很多时候取决于你的配置。对于存储过程,函数,视图之类的功能,现在两个数据库都可以支持了。另外多线程架构和多进程架构之间没有绝对的好坏,oracle在unix上是多进程架构,在windows上是多线程架构。很多pg应用也是24/7的应用,比如skype. 最近几个版本VACUUM基本不影响PGSQL 运行,8.0之后的PGSQL不需要cygwin就可以在windows上运行。至于说对于事务的支持,mysql和pgsql都没有问题。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Tsar是淘宝的一个用来收集服务器系统和应用信息的采集报告工具,如收集服务器的系统信息(cpu,mem等),以及应用数据(nginx、swift等),收集到的数据存储在服务器磁盘上,可以随时查询历史信息,也可以将数据发送到nagios报警。 Tsar能够比较方便地增加模块,只需要按照 tsar 的要求编写数据的采集函数和展现函数,就可以把自定义的模块加入到tsar中。 安装 Tsar目前托管在GitHub上,下载编译安装步骤: [azureuser@mono tsar-master]$sudo wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-check-certificate [azureuser@mono tsar-master]$ sudo unzip tsar.zip [azureuser@mono tsar-master]$ cd tsar [azureuser@mono tsar-master]$ sudo make [azureuser@mono tsar-master]# sudo make install 定时任务配置:/etc/cron.d/tsar,负责每分钟调用tsar执行采集任务;日志文件轮转配置:/etc/logrotate.d/tsar,每个月会把tsar的本地存储进行轮转;Tsar配置文件路径:/etc/tsar/tsar.conf,tsar的采集模块和输出的具体配置;模块路径:/usr/local/tsar/modules,各个模块的动态库so文件;Tsar配置 Tsar刚安装完,还没有历史数据,想要check是否正常,执行tsar -l,查看是否有实时信息输出: [azureuser@mono tsar-master]$ tsar -l Time ---cpu-- ---mem-- ---tcp-- -----traffic---- --sda--- --sdb--- ---load- Time util util retran pktin pktout util util load1 17/08/13-02:52:11 0.20 19.78 0.00 0.00 0.00 0.40 0.00 0.00 Tsar的配置主要都在/etc/tsar/tsar.conf中,常用的有: 增加一个模块,添加 mod_ on 到配置文件中打开或者关闭一个模块,修改mod_ on/offoutput_stdio_mod 能够配置执行tsar时的输出模块output_file_path 采集到的数据默认保存到的文件(如果修改的话需要对应修改轮转的配置/etc/logrotate.d/tsar)output_interface 指定tsar的数据输出目的,默认file保存本地,nagios/db输出到监控中心/数据库中,这两个功能还需要结合其它配置Tsar使用 查看历史数据,tsar-l/–list 查看可用的模块列表-l/–live 查看实时数据,tsar -l –cpu-i/–interval 指定间隔,历史,tsar -i 1 –cpu–modname 指定模块,tsar –cpu-s/–spec 指定字段,tsar –cpu -s sys,util-d/–date 指定日期,YYYYMMDD或者n代表n天前-C/–check 查看最后一次的采集数据-d/–detail 能够指定查看主要字段还是模块的所有字段-h/–help 帮助功能高级功能 输出到nagios配置: 首先配置output_interface file,nagios,增加nagios输出 然后配置nagios服务器和端口,以及发送的间隔时间 The IP address or the host running the NSCA daemon server_addr nagios.server.com The port on which the daemon is running - default is 5667 server_port 8086 The cycle of send alert to nagios cycle_time 300 由于是nagios的被动监控模式,需要制定nsca的位置和配置文件位置 nsca client program send_nsca_cmd /usr/bin/send_nsca send_nsca_conf /home/a/conf/amon/send_nsca.conf 接下来制定哪些模块和字段需要进行监控,一共四个阀值对应nagios中的不同报警级别 tsar mod alert config file threshold [hostname.]servicename.key;w-min;w-max;c-min;cmax; threshold cpu.util;50;60;70;80; 输出到mysql配置: 首先配置output_interface file,db,增加db输出 然后配置哪些模块数据需要输出 output_db_mod mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udpmod_io 然后配置sql语句发送的目的地址和端口 output_db_addr console2:56677 目的地址在该端口监听tcp数据,并且把数据入库即可,可以参照tsar2db:https://github.com/kongjian/tsar2db 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
SOAPAction HTTP request header被用来标识SOAP HTTP请求的目的地,其值是个URI地址。SOAP发送并不限制格式、URI特征或其必须可解析,那么在这种情况下,发送一个HTTP SOAP请求时,其HTTP客户端必须使用/指明SOAPAction HTTP request header。 SOAPAction header的内容可以被用在服务端,诸如:防火墙适当的过滤基于HTTP的SOAP请求消息等场景。SOAPAction header的值为空串("")表示SOAP消息的目的地由HTTP请求的URI标识;无值则表示没有指定这条消息的目的地。 跨平台调用Web Service出现:"服务器未能识别 HTTP 标头 SOAPAction 的值"的解决办法: 症状一: Web Service + ASP.NET 应用程序部署到服务器默认目录中,在IE中用http://<服务器地址>/<程序目录名>/<默认启动页面名>发生“服务器未能识别 HTTP 标头 SOAPAction 的值”错误。 症状二: 在通过WCF 客户端ChannelFactory<> 上调用.NET Web Service的服务时,出现"服务器未能识别 HTTP 标头 SOAPAction 的值"。 解决对策: 给.NET的WebService类(即.asmx文件下的类)添加属性[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)] /// <summary> /// Summary description for Service1 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [SoapDocumentService(RoutingStyle= SoapServiceRoutingStyle.RequestElement)] [System.ComponentModel.ToolboxItem(false)] // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. // [System.Web.Script.Services.ScriptService] public class SubmitFormTestService : System.Web.Services.WebService 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
DMZ是英文“demilitarizedzone”的缩写,中文名称为“隔离区”,也称“非军事化区”。它是为了解决安装防火墙后外部网络不能访问内部网络服务器的问题,而设立的一个非安全系统与安全系统之间的缓冲区,这个缓冲区位于企业内部网络和外部网络之间的小网络区域内,在这个小网络区域内可以放置一些必须公开的服务器设施,如企业Web服务器、FTP服务器和论坛等。另一方面,通过这样一个DMZ区域,更加有效地保护了内部网络,因为这种网络部署,比起一般的防火墙方案,对攻击者来说又多了一道关卡。 通过DMZ区域设置反向代理,反向代理很普遍,在Linux可以使用Nigix提供的功能,在Windows系统可以使用IIS7的Application Request Routing来完成这个功能。Making WCF RIA Services work in a DMZ/Multitier architecture using Application Request Routing文章讨论了使用ARR发布WCF RIA Service。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥。如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一。 在本文中,我将解释我如何清理和替换重复、 混乱遍布许多方法在应用程序中的代码使用ASP.NET Web API 的筛选器来完成ASP.NET Web API 接口执行时间监控。我们的项目中有如下的需求:我的工作相关的项目 (使用 ASP.NET Web API 框架) 要求记录下服务接口的调用执行时间以及请求延迟、 故障率每秒的请求总数,以帮助运营团队。 Web API 筛选器是你放到Action上的自定义属性方法 (或Controller) 添加常用功能。 Web API 筛选使您得以添加预处理和后处理的行为,本文的代码来自于How to intercept all the ASP.NET WebApi controller action methods calls with Ninject interception for logging? 和 Log duration of an ASP Web API action 。 下面是详细代码: using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Web; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace ContactManager.Filters { public class TimingActionFilter : ActionFilterAttribute { private const string Key = "__action_duration__"; public override void OnActionExecuting(HttpActionContext actionContext) { if (SkipLogging(actionContext)) { return; } var stopWatch = new Stopwatch(); actionContext.Request.Properties[Key] = stopWatch; stopWatch.Start(); } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { if (!actionExecutedContext.Request.Properties.ContainsKey(Key)) { return; } var stopWatch = actionExecutedContext.Request.Properties[Key] as Stopwatch; if (stopWatch != null) { stopWatch.Stop(); var actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName; var controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName; Debug.Print(string.Format("[Execution of{0}- {1} took {2}.]", controllerName, actionName, stopWatch.Elapsed)); } } private static bool SkipLogging(HttpActionContext actionContext) { return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() || actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any(); } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)] public class NoLogAttribute : Attribute { } } 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
XB 软件公司最近发布了JavaScript UI 库Webix ,其中包含的组件超过45个,用这些组件可以构建跟HTML5 和 CSS3 兼容的程序,这些程序不仅能在个人电脑上运行,还能用在iOS、 Android 和 Blackberry 设备上运行。它能访问离线web存储、地理位置( geolocation) API、能在画布上绘图,并集成了jQuery 和 Backbone.js。 Webix提供了简单的服务端集成控件,PHP、 ASP.NET、Java和 Ruby等各种技术都可以跟客户端的Webix部件直接通讯。此外这些组件还能用在一些MVC框架中,比如RoR、ASP.NET MVC、Spring、Struts 和 Grails. 在写这篇新闻时, Webix 库中包含的组件 有 Accordion、Calendar、Carousel、Chart、Colorboard、Context、ContextMenu、 DataTable、Dataview、Form、Form控件、Grouplist、HTMLform、IFrame、Layout、Resizer、List、Menu、Multiview、 Popup、Property Sheet、Scrollview、 Tabview、 Template、 Toolbar、 Tree、Treetable、 Unitlist、Uploader 和 Window。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
环境: 操作系统:Windows 2003 Server SP2 PHP 版本:php-5.2.6-Win32 1.下载 FastCGI For IIS6 http://www.iis.net/download/fastcgi 下载之后,双击运行进行安装。 安装后在 C:WINDOWSsystem32inetsrv 目录下产生了五个文件。如下图: fcgiext.dll – fastcgi处理程序fcgiext.ini – 配置文件fcgiconfig.js – FastCGI的控制脚本 同时在 IIS 的 “Web 服务扩展”里多了 FastCGI Handler。 2.下载 PHP5.2.14 Windows 版 http://www.php.net/downloads.php 下载 .zip 格式的版本,下载后解压至 c:PHP 目录,并给 IIS 启动帐户组或用户赋予读取和运行权限。如下图: 你可以根据自己的意愿解压到别的目录。 注册 PHP 到 FastCGI 打开 C:WINDOWSsystem32inetsrvfcgiext.ini 文件。 ; This is the configuration file for the FastCGI handler for IIS 6.0. ; The FastCGI handler will look for this file in the same directory as ; fcgiext.dll. By default, the FastCGI installer will place this file into ; the %windir%system32inetsrv directory. 我个人的理解是,只要“Web 服务扩展”里的 FastCGI Handler 为允许时,在加载 fcgiext.dll 时,会读取 fcgiext.ini 配置文件的内容,根据里面的配置为每个网站提供映射。 在 [Types] 下添加以下配置: [Types] php=PHP [PHP] ExePath=C:\PHP\php-5.2.14-Win32\php-cgi.exe “php”表示扩展名,“PHP”是配置节名称,以“[PHP]”定义。 配置 php.ini 将 C:PHPphp-5.2.14-Win32php.ini-recommended 复制一个,然后重命名为 D:PHPphp.ini 打开 C:PHPphp-5.2.14-Win32php.ini,修改: extension_dir = "C:\PHP\php-5.2.14-Win32\ext" fastcgi.impersonate = 1 其它的根据实际需要对 php.ini 进行设置修改,这里只针对能跑 php,修改完记得重启 IIS。 配置网站 右键网站 => 属性 => 主目录 => 配置 => 添加,如下图配置: 可执行文件路径:C:WINDOWSsystem32inetsrvfcgiext.dll 写个 php 测试下吧 <?php phpinfo(); ?> 看到类似以下效果说明你的服务器可以跑 php 了。 打开后如果出现提示:No input file specified. 估计是没配置 fastcgi.impersonate。 参考 http://hi.baidu.com/imdao/blog/item/16583512f11cb654f819b858.html Configure the FastCGI Extension for IIS 6.0 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
用 Redirect 方法可将浏览器重定向到另一个 URL,而不是将内容发送给用户。 这里有一篇文章介绍使用Redirect《Using Response.Redirect Effectively》 ,文章详细的讨论了Response.Redirect ,给出了一段代码: public static class HttpResponseExtensions { public static void RedirectUser(this HttpResponse response, string url) { if (response.IsRequestBeingRedirected) return; response.Redirect(url, false); var context = HttpContext.Current; if (context != null) { context.ApplicationInstance.CompleteRequest(); } } } 另外ASP.NET 4 增加了一个RedirectPermanent方法,该方法同样是重定向,但生成的HTTP响应状态不是上边所演示的302,而是301(永久跳转),301 是对搜索引擎最友好的重定向方式。你有个网站http://www.cnblogs.com ,当人们访问http://www.cnblogs.com 这个URL时,你就把他们重定向到http://www.cnblogs.com/shanyou/,那么当搜索引擎爬到http:www.cnblogs.com这个网址时,如果它不能很好地跟随重定向,则它将认为http://www.cnblogs.com页面时没有内容的,所以这个页面的排名将会非常靠后。 如果我们把一个地址采用301 跳转方式跳转的话,搜索引擎会把老地址的PageRank等信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Microsoft最近发布了SvcPerf,它是一个端到端的基于Windows事件追踪(ETW)的追踪查看器,可用于基于清单的追踪。你能够通过这个工具查看ETL文件或者实时跟踪会话,还能创建自定义的查询。 这个端到端的追踪分析工具基于Linq over Traces(TX),可以用于WCF、WF以及其他基于活动的ETW跟踪。你能够通过这个工具查看ETL文件或者实时跟踪会话,还能创建自定义的查询。 还可以在命令行提示符中使用SvcPerf转储原始的事件或者使用Linq over Traces(TX)执行自定义查询。与其他工具相比,该工具还为原始的ETL文件提供了支持。除了ETL查看器之外,它还是一个构建在LINQ to Traces (TX)之上的查询引擎,文件数目限制为64。 为了使用该工具,你需要双击SvcPerf.exe 并定位到ETL文件(也称为Windows性能分析器追踪文件)。在时间轴加载之后,需要按F5键查看事件日志。在此之后,你可以按照用户指南中列出的步骤执行过滤操作。 还可以从命令行提示符中加载ETL文件 SvcPerf <File_Name> 还可以加载清单 ,一个定义了所有事件的XML的文件,事件提供者在写入布局信息时也会写入该文件。可以通过Manifest 菜单下面的Add Manifest选项加载清单文件或者从命令行提示符中加载: SvcPerf.exe /m:<Manifest1> /m:<Manifest2> SvcPerf也支持源(Source)、视图(View)和搜索(Search)这样的动态过滤器。在源模式下,过滤器会被应用到进入的事件源。视图模式允许你捕获内存中的事件源流,并在它们上面应用过滤器。搜索模式能够对载入网格的事件执行大小写不敏感的搜索。你还可以使用表达式过滤器,在官方的用户指南上对此有详细的说明。此外,可以使用ActivityId域或者RelatedActivityId域过滤指定活动的日志。 “对WCF开发者而言,SvcPerf是一个非常有用的工具,” Altacode公司的软件开发人员Arman McHitaryan说。 还可以使用SvcPerf工具执行任意表单查询,并利用Dump()扩展以表格或者图形化表单(例如 柱状图 或性能计数器)的方式展示结果。Microsoft在随同工具一起发布的用户指南中详细解释了与工具相关的所有概念,同时还有源码帮助和屏幕截图。 “.NET Framework能够提供更好的ETW支持真的非常好。事件源是一个不错的开始,但是因为缺乏通道支持事件查看器不能获得好的可见性,” Colin Bowern说。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
首先介绍一下NESPER的大体结构,NEsper从内容上分为两块,NEsper的核心NEsper.dll和NEsper.IO.dll。 (1)NEsper的核心包包含了EPL语法解析引擎,事件监听机制,事件处理等核心模块。 (2)NEsper的io包含从各种数据源读取数据以及将输出结果写入各种数据源,包括excel,database,msmq,http,socket,XML。 贴一张esper官网上的结构图,方便大家了解esper的结构 nesper 接下来对上述结构图进行详细的解释让大家加深对ESPER的了解 Event对象:NESPER处理的事件的最小单位,一个任意的CLR对象,属性支持简单的CLR类型、数组、map、以及嵌套POCO,很灵活. 2.EPL:EPL是ESPER的核心,它类似于SQL,但是和SQL的执行方式不同。 SQL是数据在那里,你每次执行SQL就会触发一次查询;而EPL是查询在这里,数据输入达到一定条件即可触发查询。 这个条件可以有多种: a).每个event对象来就触发一次查询,并只处理当前对象 select * from OrderEvent 这个EPL语句会在每个OrderEvent对象到达后,并将该event交给后续的Listener(后面会讲到)来进行处理。但是这种用法不多见,意义不大。 b).窗口处理模式: EPL最大的特色就是这个窗口处理模式,有两种窗口,时间窗口和长度窗口。 时间窗口 : 大家想一下,如果有一个场景,要获取最近3秒内OrderEvent的price的平均值,那该怎么做呢?一般的做法需要做个后台线程来做3秒的时间统计,时间到了再做后续处理,虽然不复杂,但是也挺繁琐的。 看看EPL是怎么做的 select avg(price) from test.OrderEvent.win:time(3 sec) win:time(3 sec)就是定义了3秒的时间窗口,avg(price)就是统计了3秒内的OrderEvent对象的price的平均值长度窗口: 长度窗口和时间窗口比较类似 select avg(price) from test.OrderEvent.win:length(100) win:length(10)就是定义了10个Event的,avg(price)就是统计了最近10个的OrderEvent对象的price的平均值以上这些都比较容易理解,虽然知道了处理方法,也比较好用,我还是比较喜欢钻研一下他的内部实现方式。先来看一张时间窗口模式的图 他仅保留最近时间窗口的对象内容,但是每个Event到来都会触发一次UpdateListener的操作 EPL语句会作为一个Statement来监听事件的到来,当New Events有新事件时就会触发UpdateListener的操作,下面是一个updateListener的简单例子,event.get("avg(price))就可以获得EPL查询所获得的price平均值,然后就可以加入自己的代码进行处理,比如将结果写入本地文件 而New Events和Old Events就是他的输入,而ave(price)操作所计算的对象就是Length Window中的内容。 public class MyListener : UpdateListener { public void update(EventBean[] newEvents, EventBean[] oldEvents) { EventBean event = newEvents[0]; Console.WriteLine("avg=" + event.Get("avg(price)")); } } 事件窗口也基本类似。 c)批量窗口处理模式 窗口模式是会在每个Event来都触发一次UpdateListener操作,如果每秒Event数量达到很大的话这种方式明显是不行的 CPU消耗会很厉害 批量窗口处理模式正好可以解决这个问题 上图的时间窗口大小为4s,他会在4s的窗口时间到达以后才将窗口中的内容一起扔给UpdateListener来进行处理,性能相对节约很多,特别是大数据量的情况下。长度批量窗口的处理模式也是类似。 上述窗口模式下内存使用情况又是如何呢?经过本人测试和研究代码发现,它会保留两个窗口的内存使用量,一个保存当前窗口的Events,一个保存上一个窗口的Events,因此在估算一个数据分析程序占用多少内存要看上面监听的EPL语句开的窗口的大小以及数据的TPS,防止内存OOM。 掌握了上面的窗口的概念,后面其他的内容都很好理解了 d) 过滤 where过滤 select avg(price) from test.OrderEvent.win:time_batch(3 sec) where price>10 having过滤 select avg(price) from test.OrderEvent.win:time_batch(3 sec) having price>10 似曾相识啊,执行方式也基本和SQL里的where 和 having差不多。在EPL里where 是在incoming Events到window之间进行过滤,having是在window到New Eventing之间进行过滤 e)聚合 count select count(price) from test.OrderEvent.win:time_batch(3 sec) where price>10 sum select sum(price) from test.OrderEvent.win:time_batch(3 sec) where price>10 group by select itemName,sum(price) from test.OrderEvent.win:time_batch(3 sec) where price>10 group by itemName 都很简单,了解SQL的都狠容易上手 f) 函数 ESPER默认加载 • System • System.Collections • System.Text 支持这些包下的函数方法,例如 select Math.round(sum(price)) from test.OrderEvent.win:time_batch(3 sec) where price>10 它还支持自定义函数,举个例子,做个计算百分比的函数 public class MyUtilityClass{ public static double computePercent(double amount, double total) { return amount / total * 100; } } 配置一下 <esper-configuration <plugin-singlerow-function name="percent" function-class="mycompany.MyUtilityClass" function-method="computePercent" /> </esper-configuration> OK了,可以用了 select percent(price,total) from OrderEvent 总体来说,ESPER的EPL功能非常强大,而且基本和SQL类似,入门容易,构造一个实时数据分析系统比较简单,且维护成本低,新应用进来只需要简单配置一下EPL语句就可以了,方便快捷,对大部分的系统还是比较适合的。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
NEsper使用的事件类型来描述事件的类型信息。你的应用在启动时可能预先配置定义事件类型,或者在运行时通过API或EPL语法动态的增加事件类型。 EPL中的create schema 的语法允许在运行时用EPL申明一个事件类型。 2.1事件对象 事件是过去发生的动作或状态变化的一个不可改变的记录。事件属性捕捉事件的状态信息。 在ESPER中,事件是可以被描述成以下任何一种CLR对象: NEsper为声明一个事件提供了多种的选择,没有绝对的需要用户去创建一个CLR对象来代表一个事件。事件表达有以下共性: • 所有的事件表示支持嵌套,索引和映射属性(亦称属性表达),在下面详细解释前。嵌套级别没有限制。 • 所有的事件表示提供事件类型元数据。这包括嵌套属性的类型元数据。 • 所有事件表示允许调换事件本身和部分属性图到新的事件。条件调换是指选择那些本身是嵌套的属性图的事件本身或事件属性,然后查询事件的性质或嵌套属性图。Apache的Axiom事件表示是一个例外,目前不允许调换的事件属性,但允许调换的事件本身。 • CLR对象和Map描述允许超类型。 所有事件表示的API的行为是相同的,在这一章中指出的少数例外。多个事件陈述的好处有: • 对于已经支持的陈述事件的应用程序,没有必要作事件到CLR对象的转换处理。 • 事件陈述是交互的,当事件陈述发生改变时,需要减少或消除变更声明。 • 事件陈述是可共同使用的,允许所有的事件表示在相同或不同报表中的共同使用。 • 选择使得其可能自觉地权衡性能,易于使用。 2.2事件属性 事件属性捕捉事件的状态信息。事件属性的简单的索引,映射和嵌套的事件属性。下表列出了不同类型的属性和它们的语法在事件表达中。该语法允许语句来查询深CLR 对象图,XML结构和MAP事件。 如下图: 合并也有可能。例如,一个有效的组合,可以的Person.Address("home”).street[0]。 2.2.1转义字符 如果你的应用程序使用System.Collection.Generic.IDictionary或者XML描述事件,事件属性名称会包括一个点号(“.”)字符。反斜杠(“”)可以用来转换点号,允许事件名称中包括点号。 select part1\.part2 from MyEvent 有时,你的事件属性可能会重叠EPL语言关键字。在这种情况下,你可以使用向后撇号'字符转义属性的名称。 下例假定一个Quote事件,有一个order的属性,而order也是一个保留关键字: select `order` from Quote 2.3动态属性 动态(未选中)属性是不需要在语句的编译时知道的事件属性。这些属性是在运行过程中解析。 动态属性背后的想法是,对于一个给定的潜在事件,我们并不总是事先知道的所有属性。一个潜在的事件可能在语句的编译时不附加属性,而我们要查询。尤其是丰富的,面向对象的域模型的事件表示非常有用的概念。 动态属性的语法包含属性的名称和一个问号。索引,映射和嵌套的属性也可以动态特性。 动态属性总是返回System.Object的类型。此外,如果在运行时动态属性不存在,动态属性返回一个空值。 例如,考虑一个OrderEvent事件提供了一个“item”属性。 “item”属性是类型对象且持有服务或产品的一个实例的引用。 假设服务和产品类提供了一个名为“price”的属性。通过一个动态的属性,我们可以指定一个查询,以获得从任一对象(服务或产品)的price属性: select item.price? from OrderEvent 另一个例子,假设Server类包含一个serviceName属性,而Product类不拥有,下面的查询返回Server对象的serviceName属性。对于没有serviceName属性的Product对象,将返回一个空值: select item.serviceName? from OrderEvent 考虑OrderEvent有多个实现类,其中有一些timestamp属性的情况。下一个查询返回的这些实现OrderEvent接口功能的实例的timestamp属性: select timestamp? from OrderEvent 上面的查询返回类型事件的单个列名timestamp? 当为嵌套的动态属性,动态属性的所有属性也考虑动态特性。在下面的例子中的查询要求direction属性对象返回的detail的动态属性: select detail?.direction from OrderEvent 上面的EPL等同于如下: select detail?.direction? from OrderEvent 与动态属性协同提供的有用的函数如下: • CAST函数动态属性(或表达式的值)转换成给定的类型。 • exists函数检查是否存在一个动态的属性。如果事件有该名称的属性,返回true,否则返回false。 • instanceof函数检查动态属性的值(或表达式的值)是否是任何给定的类型。 • typeof函数返回字符串类型的动态属性名称。 动态事件属性与所有CLR对象,基于Map和XML基于DOM的事件一起工作。 2.4 Fragment and Fragment 类型 有时一个事件的属性能是事件本身。ESPER使用条款碎片和碎片类型来表示这种事件。最好的例子是一个模式相匹配的两个或两个以上的事件且输出事件包含匹配的事件作为片段。换句话说,输出事件由更多的事件,碎片组成的复合事件。 片断具有相同的元数据作为其封装的复合事件。封装的复合事件的元数据包含属性是片段的信息,或有一个属性值能代表片断或者事件本身。 片段和类型的元数据,可以让您的应用程序导航的复合事件,而不需要使用CLR反射API和减少耦合底层的事件表示。 2.5普通的原CLR对象事件 普通的旧式CLR对象的事件是通过CLR 风格的getter方法,暴露事件属性的对象实例。事件类或接口不完全符合CLR 规范的;但是Esper引擎来获取事件属性,所需的Get属性,必须是当前的或一个可以通过配置中定义的访问器方法。 NEsper支持CLR 风格的事件类扩展的超类或实现一个或多个接口。此外,NEsper事件模式和EPL申明可以参考CLR 接口类和抽象类。 代表事件的类应是一成不变的。由于事件是记录状态改变或过去发生的行动,有关事件属性不应该改变的。然而,这是不是一个硬性的要求,NEsper引擎接受事件还是可变的。 没有必要实现GetHashCode和Equals方法。这些方法的实施是CLR事件类,不影响引擎的任何方式的行为。 2.5.1 CLR对象事件 如前所述,不同的属性类型都支持标准的CLR规范,且有些具有NEsper的独特支持: • Simple- 属性可以检索单个值。相关的属性类型可能是原始CLR 语言(如INT,一个简单的对象(如System.String),或更复杂的对象,复杂对象是由CLR语言的应用程序定的,或一个类库包含的应用程序。 • Indexed -索引属性存储,可以单独由一个整数值,非负指数(或下标)来访问的对象(同一类型的所有)的有序集合。 • Mapped -NEsper接受字符键值对映射属性的任何属性。 • Nested -嵌套属性是一个属性所属的CLR对象本身就是另一个事件的属性。 如下图所示,假设有NewEmployeeEvent事件类。在这个例子中返回CLR对象的映射和索引属性,但也可能返回CLR 语言中的原始类型(如int或String)。Address对象和Employee有嵌套属性,如Address对象的街道名称或Employee对象的雇员名称。 public class NewEmployeeEvent { public String FirstName { get; } public Address GetAddress(String type); public Employee GetSubordinate(int index); public Employee[] AllSubordinates { get; } } Simple事件属性需要返回属性值的getter属性。在这个例子中,FirstName 属性返回String型的firstName属性。 Indexed事件属性要求任何一个以下的getter方法。一是采用一个整数类型作key值,并返回该属性的值的方法,如GetSubordinate,或一个返回数组类型,或实现迭代的类的方法。例如getSubordinates 方法,返回一个Employee 数组,但也可能返回一个可迭代的。 EPL或事件模式的语句,索引属性通过[index]语法访问。 Mapped事件属性需要一个getter方法,该方法通过键值对并返回该属性的值,如GetAddress方法。 EPL或事件模式声明,映射属性通过属性(“key”)语法访问。 Nested事件属性需要一个getter方法返回嵌套对象。 GetAddress和 GetSubordinate方法映射和索引返回一个嵌套对象的属性。 EPL或事件模式声明,嵌套的属性是通过property.nestedProperty语法访问。. 所有事件的模式和EPL表达式允许使用索引,映射和嵌套属性(或这些的联合)。下面的例子显示事件模式表达式的过滤器(每行是一个单独的EPL表达式)的索引,映射和嵌套属性的不同组合: every NewEmployeeEvent(firstName='myName') every NewEmployeeEvent(address('home').streetName=' Park Avenue') every NewEmployeeEvent(subordinate[0].name='anotherName') every NewEmployeeEvent(allSubordinates[1].name='thatName') every NewEmployeeEvent(subordinate[0].address('home').streetName='Water Street') 同样,语法可用于在EPL表达式在所有可以预测的事件属性名称的情况下,如在select列表,where条件或加入标准。 select firstName, address('work'), subordinate[0].name, subordinate[1].name from NewEmployeeEvent where address('work').streetName = 'Park Ave' 2.5.2属性名称 NEsper配置提供了一个关闭区分大小写的属性名称的标志。下图是getter方法和属性名称的示例列表: 2.5.3常量和枚举 常量是在CLR 类中用public static const声明的成员,也可参与各种表现形式,如这个例子所示: select * from MyEvent where property=MyConstantClass.FIELD_VALUE 事件属性是枚举值可以比较他们的枚举值: select * from MyEvent where enumProp=EnumClass.ENUM_VALUE_1 另外,类中可以声名静态的方法,如枚举类EnumClass如下: select * from MyEvent where enumProp=EnumClass.valueOf('ENUM_VALUE_1') 如果您的应用程序不引入,通过配置枚举类的包,它必须指定类的包名。枚举类是内部类必须遵守CLR约定使用"+"。 例如:枚举类Color是MyEvent的内部类,在org.myorg包中可以引用如下所示: select * from MyEvent(enumProp=org.myorg.MyEvent+Color.GREEN).std:firstevent() 实例方法也可能被调用事件实例指定一个流名称,如下所示: select myevent.computeSomething() as result from MyEvent as myevent 链接的实例方法是支持的,如这个例子说明: select myevent.GetComputerFor('books', 'movies').Calculate() as result from MyEvent as myevent 2.5.4参数化的类型 当你的getter方法或访问器成员返回一个类型,例如索引属性IEnumerable或者映射属性IDictionary,于是属性表达式可能通过参数类型引用属性 一个参数化类型的事件的属性例子是: **public class NewEmployeeEvent { public String Name { get; } public IEnumerable<EducationHistory> Education { get; } public IDictionary<String, Address> Addresses { get; } }** 此事件的有效属性表达式的示例如下所示: select Name, Education, Education[0].Date, Addresses('home').Street from NewEmployeeEvent 2.6.1概述 事件也可以被实现了System.Collection.IDictionary 接口的对象代表。Map事件的属性是map值,通过了System.Collection.IDictionary接口暴露的get方法访问。 Map事件类型是一个综合型的系统,它可以消除需要使用CLR类的事件类型,从而更容易在运行时改变的类型或从其他来源产生的类型信息. 一个给定的Map事件类型可以有一个或多个也是map类型的超类,它可用到在任何Map超类型上可用的所有属性类型。此外,在EPL内的任何地方,使用一个map超类的事件类型名称,任何map子型及它们的子型都匹配表达式。 你的应用程序在运行时通过配置操作UpdateMapEventType,可以添加属性到现有的Map事件类型中。map属性不会被更新或删除 ,只能添加属性,嵌套的属性也可以添加。运行时配置也允许删除map事件类型和添加新的类型的信息。 在您的应用程序配置map事件类型通过提供一个类型名称,类型名称可用于进一步的map事件类型定义,去指定属性类型或一个数组属性类型的类型名称。 一对多关系在Map事件类型中是通过数组表示,一个在Map事件类型中的属性可能是一个简单的数组,一个CLR 对象组或是一个map组。 引擎在EPRuntime接口中通过SendEvent(DataMap map, String eventTypeName)方法来执行Map事件。实例在map中表现为事件属性。Key值必须是字符串,引擎才能找到Pattern或者EPL指定的事件属性名。 引擎不会验证事件类型名称或值。你的应用程序应确保通过的对象作为事件属性匹配create schema 属性名和类型,或者在运行时配置事件类型信息或静态配置。 2.6.2 MAP属性 Map事件属性可以是任何类型。Map属性是CLR应用程序提供对象: • 如前所述,属性是CLR应用程序对象可以通过嵌套,索引,映射和动态属性的语法查询。 • Map类型的属性可以嵌套任意深度,因此可以被用来表示复杂的域信息。嵌套,索引,映射和动态属性的语法,可以用来在Map或数组内查询。 为了使用Map事件,事件类型名称和属性名称和类型必须通过配置让引擎知道。请参见13.4.2节的例子,“System.Collection.Generic.IDictionary的代表事件”。 下面的代码片断创建和处理Map事件。它首先定义了一个CarLocationUpdateEvent事件类型: var mapEvent = new Dictionary<string,object>(); mapEvent["carId"] = carId; mapEvent["direction"] = direction; epRuntime.SendEvent(mapEvent, "CarLocUpdateEvent"); CarLocUpdateEvent现在能用在EPL表达式中 select carId from CarLocUpdateEvent.win:time(1 min) where direction = 1 该引擎还可以通过嵌套属性的语法,查询CLR 对象在Map事件中的值。因此,Map事件,可用于聚合多个数据结构到一个简单事件,时行方便的综合信息查询。下面的例子演示Map事件与account 对象。 var mapEvent = new Dictionary<string,object>(); mapEvent["txn"] = txn; mapEvent["account"] = account; epRuntime.SendEvent(mapEvent, "TxnEvent"); 2.6.3 MAP父类 你的Map事件类型可以声明一个或多个超类型,在引擎初始化时或运行时,通过管理界面配置。 Map事件类型的超类,也必须是Map事件类型。父类所有属性名称和类型也可在子类中重载。此外,在EPL中,一个Map超类的事件类型名称用被应用,任何子类表达式也相匹配(类似于CLR 接口的概念)。 这个例子假定BaseUpdate事件类型已经声明,且作为一个AccountUpdate事件类型的超类(两个都是Map事件类型): epService.EPAdministrator.GetConfiguration(). AddEventType("AccountUpdate", accountUpdateDef,new String[] {"BaseUpdate"}); 你的应用程序EPL表达式中可能会选择BaseUpdate事件,会收到BaseUpdate和 AccountUpdate事件,以及BaseUpdate的任何其它子类。 select * from BaseUpdate 你的应用程序Map事件类型可能有多个超类。多重继承层次结构之间的MAP可以任意深度,但是循环依赖是不允许的。如果使用运行时配置,增加子类时,必须父类先存在。 2.6.4 MAP高级属性类型 嵌套属性: 强壮的类型嵌套的map事件可以被用来建立丰富,类型安全的事件类型。使用AddEventType方法配置在初始化时或运行时定义的类型。值得注意的地方: • CLR 的对象(POCO),可以作为属性出现在MAP嵌套中。 • 一个Map中便用的事件类型名称可能代表一个Map嵌套,或者Map嵌套数组. • 嵌套的级别没有限制 • 动态属性,可以用来查询Map内可能无法预先知道的key. • 在嵌套结构的访问路径后面不能映射不存在的实体,该引擎返回的属性为null。 一对多关系: 对在map内模型重复的属性,你可以使用Map的属性数组。你可以使用原始类型的数组或CLR 对象的数组或一个先前定义的Map事件类型的数组. 当使用先前宣布的Map事件类型作为一个数组属性,literal[]必须追加在事件类型名称后。. 下面的例子定义了一个名称Sale的Map事件类型,拥有各类型的数组属性。它假定SalesPerson 的CLR 类存在和OrderItem的被声明为一个Map事件类型: Map<String, Object> sale = new HashMap<String, Object>(); sale["userids"] = typeof(int[]); sale["salesPersons"] = typeof(SalesPerson[]); sale["items"] = "OrderItem[]"; // The property type is the name itself appended by [] epService.EPAdministrator.GetConfiguration(). AddEventType("SaleEvent", sale); 上面的例子中声明的三种属性: • 整数类型数组userid • 对象数组 SalesPerson • Map类型数组 orderitems. 下来的EPL声明对数组属性值查询的示例: select userids[0], salesPersons[1].name,items[1], items[1].price.amount from SaleEvent 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
EverBox网盘(www.everbox.com)是由盛大创新院推出的一款网盘产品,提供了超大的免费存储空间(可升级到 10GB),支持文件同步、文件分享、在线浏览照片、在线听音乐等功能,并提供 Windows 客户端程序。其中有一项是可以使用第三方的账号注册使用,也就是OAuth登陆,说的更具体的就是用OpenID了,谁需要EverBox的邀请可以给我留言或者QQ上找我。 OpenID 是一个以用户为中心的数字身份识别框架,它具有开放、分散、自由等特性。 OpenID 的创建基于这样一个概念:我们可以通过 URI (又叫 URL 或网站地址)来认证一个网站的唯一身份,同理,我们也可以通过这种方式来作为用户的身份认证。由于URI 是整个网络世界的核心,它为基于URI的用户身份认证提供了广泛的、坚实的基础。 OpenID 系统的第一部分是身份验证,即如何通过 URI 来认证用户身份。目前的网站都是依靠用户名和密码来登录认证,这就意味着大家在每个网站都需要注册用户名和密码,即便你使用的是同样的密码。如果使用 OpenID (参见规范),你的网站地址(URI)就是你的用户名,而你的密码安全的存储在一个 OpenID 服务网站上(你可以自己建立一个 OpenID 服务网站,也可以选择一个可信任的 OpenID 服务网站来完成注册)。具体可以参考园友的文章 如何在ASP.NET中创建OpenID。 下面的部分我重点是在如何把自己网站的账号通过OpenID开放出来,类似于QQ,Gmail,baidu,盛大通行证账号的一键式登陆。 OpenID协议非常易于扩展,下面的图表展示了OpenID2.0草案的基本工作流程。它展示了在终端用户、Relying Party站点(一个示例站点)和OpenID服务提供者之间的交互过程(最常见的认证流程),更详细的信息参考OpenID使用手册。 国际化资源标识符对于OpenID中的XRI的支持是必不可少的一项,.NET 3.5之后的版本对国际化资源标识符支持很好了,国际化资源标识符支持Web 地址通常使用由一组非常有限的字符组成的通用资源标识符 (URI) 来表示。一般来说,这些地址中只能包含英文字母表中的大、小写字母、数字 0 到 9 以及少量其他包括逗号和连字符在内的 ASCII 符号。对于世界上使用非拉丁字母字符集(如日文和希伯莱文)的地区来说,这种语法不是很方便。设想一下诸如 www.BaldwinMuseumOfScience.com 的地址,如果您讲英语,这个地址便很容易理解和记忆。但是,如果您不会说英语,则这个 URL 看上去跟符号的随机排列没什么差别。如果您只会说英语,您能记住用中文写的一长串地址吗?国际化资源标识符(或 IRI)支持非 ASCII 字符,或者更准确的说是 Unicode/ISO 10646 字符。这意味着域名可以包含 Unicode 字符,即可以有这样的 URL:http://微軟香港.com。我们已将现有的 System.Uri 类扩展为根据 RFC 3987 提供 IRI 支持(请参见 faqs.org/rfcs/rfc3987.html)。对于当前的用户来说,除非他们特意选择启用 IRI 功能,否则不会看到 .NET Framework 2.0 的行为有任何变化。原因是我们要确保 3.5 版本与以前版本的应用程序兼容。如果选择采用,您必须做两项更改。首先,将下列元素添加到 machine.config 文件: 然后,指定是否应将国际化域名 (IDN) 分析应用到域名中,以及是否应该应用 IRI 分析规则。这可以在整个计算机范围的 machine.config 或单个应用程序的 app.config 中进行,如:复制代码 <uri> <idn enabled="All" /> <iriParsing enabled="true" /> </uri> </configuration> 启用 IDN 可以将域名中的所有 Unicode 标签转换成其 Punicode 等同项。Punicode 名称只含有 ASCII 字符,而且总是以前缀“xn--”开头。这是因为 Internet 上目前部署的大多数 DNS 服务器仅支持 ASCII 字符。启用 IDN 只会影响 Uri.DnsSafeHost 属性的值。对于微軟香港.com 来说,它包含 xn--g5tu63aivy37i.com,而 Uri.Host 将包含 Unicode 字符。根据您所使用的 DNS 服务器,在 idn 元素的已启用属性中,有三种可能的 IDN 值供您使用:“All”会将 IDN 名称 (Punicode) 用于所有域名。 “AllExceptIntranet”会将 IDN 名称用于所有外部域名,而将 Unicode 名称用于所有内部域名。仅当 Intranet DNS 服务器支持 Unicode 名称时,这种情况才适用。“None”是默认值,它和 .NET Framework 2.0 的行为相符。 启用 IRI 分析 (iriParsing enabled = "true") 后,系统会根据 RFC 3987 中的最新 IRI 规则进行规范化和字符检查。当默认值为 false 时,则会根据 RFC 2396(请参见 faqs.org/rfcs/rfc2396.html)进行规范化和字符检查。要了解有关通用资源标识符和 Uri 类的更多信息,请参阅在线文档,地址为msdn2.microsoft.com/system.uri。 .NET下使用OpenID,有两种解决方案,第一个就是基于开源的社区解决方案 :dotnetopenauth. 网址为: http://www.dotnetopenauth.net/,第二个是基于微软的Windows身份验证基础(Windows Identity Foundation (WIF))。 先简要介绍一下WIF,Windows身份验证基础 (先前代号为 Geneva 框架) 是微软.NET框架的一个新拓展,它帮助开发者构建具有声明意识的应用程序(这将使您的应用程序的用户认证客观化),改善开发者生产力,增强应用程序安全性,提供协同合作性。基于可协同合作的标准协议,WIF以及基于声明的身份验证模式,可以使得在云端或非云端的ASP.NET与WCF的应用程序,实现单点登陆,个性化,联合化,强验证,身份验证委托,以及其他验证功能。 使用WIF,无论应用程序托管于非云端还是Windows Azure,开发者可以使用单一的编程模式来处理身份验证。 因为您只需学习一种模式和一套工具,您的生产力得到了提高,并且如果改变托管的环境,您也可以迅速的上手。因为不论应用程序托管于哪里,模式是不变的,所以使用WIF可以更便捷的将非云端应用程序迁移至Windows Azure(从身份验证的角度),反之亦然。 基于WIF来提供OpenID服务可以参考codeplex上的一个项目http://startersts.codeplex.com/,网站上有很详细的文档,不过相对来说配置比较麻烦点。 下面我们具体介绍基于dotnetopenauth的服务提供者,首先从http://www.dotnetopenauth.net/下载,在例子中有两个Provider(OpenIdProviderMvc、OpenIdProviderWebform)。例子中使用ReadOnlyXmlMembershipProvider,很容易的替换掉这个MembershipProvider为你的用户系统MembershipProvider,就可以将你的用户系统改造成OpenID服务。 默认的示例里头只返回给 Relying Party很少信息. 一般只有两个,一个是:FriendlyIdentifierForDisplay ,就是用户名,一个是ClaimedIdentifier, 是用户的标识.。一般我们还要抓到用户的Email,和个性图标.等等一些有用的东西.但是默认的是不返回的。先看看可以返回什么信息. DotNetOpenAuth中有一个WellKnownAttributes 类, 这个类中定义了一系列可以返回的信息 如何向外提供这些信息呢? 请看下面的示例代码 : [Authorize] public ActionResult SendAssertion() { IAuthenticationRequest authReq = PendingAuthenticationRequest; PendingAuthenticationRequest = null; // clear session static so we don't do this again if (authReq == null) { throw new InvalidOperationException("There's no pending authentication request!"); } if (authReq.IsDirectedIdentity) { authReq.LocalIdentifier = Models.User.GetClaimedIdentifierForUser(User.Identity.Name); } if (!authReq.IsDelegatedIdentifier) { authReq.ClaimedIdentifier = authReq.LocalIdentifier; } // Respond to AX/sreg extension requests. //// Real web sites would have code here ClaimsResponse sregResponse = null; var sregRequest = authReq.GetExtension<ClaimsRequest>(); if (sregRequest != null) { MembershipUser user = Membership.GetUser(); if (user != null) { sregResponse = sregRequest.CreateResponse(); //sregResponse.BirthDate = user. sregResponse.Email = user.Email; sregResponse.FullName = user.UserName; } authReq.AddResponseExtension(sregResponse); } authReq.IsAuthenticated = this.UserControlsIdentifier(authReq); return OpenIdProvider.PrepareResponse(authReq).AsActionResult(); } 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
一、概述 性能监视,是Windows NT提供的一种系统功能。Windows NT一直以来总是集成了性能监视工具,它提供有关操作系统当前运行状况的信息,针对各种对象提供了数百个性能计数器。性能对象,就是被监视的对象,典型例子有Processor、Process、Memory、TCP/UDP/IP/ICMP、PhysicalDisk等。计数器通常提供操作系统、应用程序、服务、驱动程序等的性能相关信息,以此来分析系统瓶颈和对系统及应用程序性能进行诊断和调优。性能计数器机制让应用程序和操作系统组件可以向性能监视应用程序,比如性能监视器(Performance Monitor),报告一些与性能有关的统计信息。PerfMon.exe中可以查看性能对象、性能计数器和对象实例,可通过添加计数器来查看相关描述信息。 实际上,可以通过编写程序来访问所有的Windows性能计数器。Windows中,注册表是访问性能计数器的一种机制。性能信息并不实际存在于注册表中,在注册表编辑器RegEdit.exe中是无法查看的,但可以通过注册表函数来访问,利用注册表键来获得从性能数据提供者那里提供的数据。打开名为HKEY_PERFORMANCE_DATA的特殊键,利用RegQueryValueEx函数查询键下面的值,就可以直接访问注册表性能计数器信息。当然,也可以利用性能数据帮助器(PDH, Performance Data Helper) API (Pdh.dll)来访问性能计数器信息。 性能日志和警报是作为 Windows 操作系统的一部分发行的一种管理性能监控工具。它依靠由各种 Windows 组件、子系统和应用程序发布的性能计数器,使您可以跟踪资源使用情况以及针对时间以图形方式绘制它们。您可以使用 Performance Logs and Alerts 来监控标准的性能计数器(例如,内存使用情况或处理器使用情况),或者您可以定义您自己的自定义计数器来监控应用程序特定的活动。 二、HKEY_PERFORMANCE_DATA数据组织 性能数据的头部是一个PERF_DATA_BLOCK结构(如图1所示),它描述系统和性能数据总体信息,可从Global键值处查询得到该结构数据。PERF_DATA_BLOCK之后,定义了系统中的全部性能对象类型(PERF_OBJECT_TYPE),其中每个对象类型头部中描述了下一个性能对象类型的偏移量Offset。 三、性能计数器的架构 性能计数器采用的是客户端服务器结构,性能数据采用共享内存存储,在应用中自定义性能计数器,在应用程序调用的时候调用性能计数器进行计数。体系结构如下: 性能计数器可以获得应用程序性能的实时度量数据,而不需要通过记日志,进行另外的处理。而且性能计数器可以远程查看,可以通过管理工具(MOM)进行管理。在损耗上也非常的小。 四、.NET性能计数器实现 在.NET Framework下有个程序集 (C:WINDOWSMicrosoft.NETFrameworkv2.0.50727perfcounter.dll)实现了性能计数器功能,包括性能计数器的安装/卸载,值的读写。 在命名空间System.Diagnostic提供了一组性能计数器类,包括PerformanceCounterCategory,PerformanceCounter,PerformanceCounterInstaller,CouterSample等等。 在.NET中性能计数器有良好的抽象封装,实现起来比C/C++容易得多。我们在应用经常只关注一些请求类型的数据度量,例如下述: Requests Started Requests Executing Requests Completed Requests Failed Request Execution Time Requests/Hour Requests/5Min Requests/Min Requests/Sec 但是真正需要做这些性能计数器的安装/卸载,计数,读取还是需要大量的代码,通过封装来简化编程接口。对于使用WCF来实现的服务,可以基于WCF的扩展性,进行进一步的封装。 .Net最佳实践3:使用性能计数器收集性能数据 http://blogs.msdn.com/b/ralarcon/archive/2012/10/03/web-app-performance-counters-compilation.aspx Monitor your SQL Server 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
对实时信息分析和处理,常常需要客户应用程序的开发相应功能。一般地,这些功能需要提供以下的处理流程,分析获取的数据,筛选数据,提取出有用的信息,然后将其通过特定的形式展现出来。由于具体实时信息的高并发性和高吞吐量的需求,这就需要客户应用程序具有高度扩展性和响应能力,而在数据处理领域。NEsper就是一个.NET 开源的针对此类问题的事件流处理解决方案,其目的在于简化有此需求的客户应用程序的开发。 1.1.CEP与事件流 NEsper 的目的在于为应用程序提供分析和响应事件的要求。典型的应用需求如下 • 业务流程管理和自动化。(提供流程监控,异常报告) • 财务(算法交易,欺诈检查,风险管理) • 网络及应用程序监控(入侵检测,SLA(Service Level Agreement)监控) • 传感器网络应用(RFID 读取,生产线调度和控制,空中交通) 这些应用的共同特点是,有实时或类实时事件处理的需求,有时也称为复杂事件处理和事件流分析。其业务事件具有吞吐量,延时性及业务的复杂性等关键因素。 • 高吞吐量 - 处理大量的消息(1000至100K每秒的消息之间的应用程序) • 低延迟 - 应用在实时条件下发生的(从几毫秒到几秒钟)的反应 • 复杂的计算 - 应用程序根据规则检测相关事件,过滤事件,将对满足条件的事件加入基于时间的事件流或基于窗口期的事件流中,当事件离开时触发相应的操作。 NEsper的事件引擎就是用于构造此类应用需求,并能扩展复杂事件处理。 1.2.CEP与关系数据库 关系数据库和结构化查询语言的目标在于处理相对静态的并且有复杂查询要求的应用系统的数据要求。因此大部分的这类数据库(基于内存的数据库除外)将数据存储在硬盘上。因此对其优化往往在于硬盘存取访问的优化。 应用程序常常利用查询来获取数据库中的数据。如果应用程序需要每秒10次查询数据,那么必然产生相应频繁的数据查询。对于每秒成百上千的大规模的请求,这种方式并非表现的很优秀。 数据库的触发器可以对的更新操作作出相应响应。然而数据库的触发器会很慢,并且不能轻松的对复杂条件进行逻辑检测和响应。 相比传统的关系数据库,在查询性能方面基于内存的数据库可能会更适合复杂事件处理应用程序。然后内存的数据库并没有针对此类查询性能需求方面有所优化。 1.3.NEsper引擎 NEsper 的工作原理有些类似数据库倒置。与传统的先存储后查询数据的方式不同。NEsper引擎预先设置查询条件,然后让实时数据通过这些查询条件,引擎抓取符合条件的数据,这种查询是连续不断的。 它提供两种方式处理这些事件,事件模式和事件流查询。 NEsper提供基于表达式的事件匹配规则。模式匹配引擎是一个状态机的实现。这种事件处理的方式是对于到达或离开的事件,进行匹配和处理。他基于时间窗口的事件流。 同样NEsper提供了另外一种方式。这种基于窗口事件流,他提供聚合,连接,分析函数,来处理这些复杂的事件。对过EPL(NEpser定义的一套类sql的语法 )查询这个事件窗口。获取满足条件的事件。EPL语言类于SQL,但是与sql也不同。在EPL中查询基于视图而非表。视图提供许多操作,用便能从事件流中获取相应的数据。 NEsper提供了相应的API,支持以上两种方式 。 1.4所需的第三方包 NEsper 的运行环境需要以下的第三方包 • ANTLR EPL syntax.的生成和解释工具, 在编译环境时需要可以访问: http://www.antlr.org 。 • CGLIB 基于. The Apache 2.0 许可的开源字节码的动态生成工具。 • Apache Log4Net 开源日志工具。 NEsper 其他编译和测试环境需要的第三方包 • NUnit 基于.NET的优秀单元测试框架。 • MySQL /SQL Server:Nesper 的 sql测试套件。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
LINQ via C# Recently I am giving a series of talk on LINQ. the name “LINQ via C#” is copied from “ CLR via C# ”, one of my favorite books. Currently part 1 – 8 are finished, and the entire series should be 10 parts. The contents are: Introducing LINQ What Is LINQ LINQ via C# Events Posters Design 10 LINQ via C# events have been held successfully. Each event is a pure English speaking technical talk. I designed some posters for the events, with no enough time to design for each event. LINQ via C# part 4 In part 3, lambda expression of C# is introduced...Introducing LINQ (1) What Is LINQ [ LINQ via C# series ] This LINQ series is from my 10 parts of LINQ via C# talks . And the poster designs for the events are here . What is LINQ Here is the roadmap of .NET and C#: Date .NET Framework CLR C# IDE Introduced Features February 13th, 2002...Introducing LINQ (2) Advancements Overview [ LINQ via C# series ] According to MSDN : LINQ is one of Microsoft’s most exciting, powerful new development technologies. Independent to data source This sample mentioned in part 1 is working on items in a .NET array: var results = from number in source...Understanding C# 3.0 Features (1) Automatic Property [ LINQ via C# series ] As the fundamental of LINQ, This chapter will explain the new language features of C# 3.0, all of which are syntactic sugars. This part is about the automatic property. In C# 2.0 a property can be declared like this: public class... Understanding C# 3.0 Features (2) Object Initializer And Collection Initializer [ LINQ via C# series ] Take this Person type as an example: public class Person { public string Name { get ; set ; } public int Age { get ; set ; } } Object initializer In C# 2.0 we create an Person instance and initialize it like this: Person person...Understanding C# 3.0 Features (3) Type Inference [ LINQ via C# series ] The “var” keyword has been introduced from the beginning . It is a new language feature called type inference in C# 3.0. Local variable type inference Consider the local variable declaration and initialization: TypeName a = b; Since...Understanding C# 3.0 Features (4) Anonymous Type [ LINQ via C# series ] This feature provides a way to create an instance without declare the type: var mark = new { Name = "Mark" , Age = 18 }; Since the type name is unknown at this time when writing code, this is called a anonymous type. Compilation...Understanding C# 3.0 Features (5) Extension Method [ LINQ via C# series ] Extension method is a fancy and powerful syntactic sugar in C# 3.0. Extension methods are very important when writing functional style C# code. Define an extension method for a class When we define an extension method for a type...Understanding C# 3.0 Features (6) Lambda Expression [ LINQ via C# series ] Lambda expression is another powerful syntactic sugar making C# functional. In this post, “Lambda expression” simply means “C# Lambda expression”. The native concept of lambda expression will be introduced in the later lambda calculus...Understanding C# 3.0 Features (7) Query Expression [ LINQ via C# series ] This kind of code has been introduced again and again: var positive = from number in source where number > 0 orderby number descending select number.ToString( CultureInfo .InvariantCulture); This is called the query expression... Understanding C# 3.0 Features (8) Partial Method [ LINQ via C# series ] The is a very simple feature. From partial class to partial method Partial class is introduced by C# 2.0. With the partial keyword, the definition of one type is able to be divided into several files. For example, if creating a...Understanding LINQ to Objects (1) Programming Paradigm [ LINQ via C# series ] Declarative vs. imperative This post mentioned that LINQ introduced new programming constructs to C#. Take a look at the samples in the beginning post : int [] source = new int [] { 0, -5, 12, -54, 5, -67, 3, 6 }; List < int...Understanding LINQ to Objects (2) Method Chaining [ LINQ via C# series ] It is obvious the Where(), OrderBy(), Select() can be invoked fluently: int [] source = new int [] { 0, 1, -2, 3, 24, 6, 3 }; var results = source.Where(item => item > 0 && item < 10) .OrderBy(item => item) ...Understanding LINQ to Objects (3) Query Methods [ LINQ via C# series ] After understanding the programming paradigm and why LINQ query methods can be chaining , this post shows the details of LINQ query methods. Methods like Where(), OrderBy(), OrderByDescending(), and Select() are exhibited again...Understanding LINQ to Objects (4) Iterator Pattern [ LINQ via C# series ] According to Wikipedia : Iterator pattern is a design pattern in which iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation. An Iterator object encapsulates...Understanding LINQ to Objects (5) Implementing Iterator [ LINQ via C# series ] Iterator pattern is the core pattern of LINQ to Objects implementation. To filter, order, or project the data items of a data collection, of course the code need to go through the collection and figure out the results. The previous...Understanding LINQ to Objects (6) Deferred Execution [ LINQ via C# series ] One post at the beginning of this series mentioned that deferred execution is a important advancement of LINQ. The following code show how is the execution deferred: IEnumerable < int > source = Enumerable .Range(-2, 5); ...Understanding LINQ to Objects (7) Query Methods Internals [ LINQ via C# series ] This post explains how are the LINQ to Objects standard query methods implemented. Once again, it will be exhibited that iterator pattern is the core pattern of LINQ to Objects query. The first thing need to emphasize is, not all...Understanding LINQ to Objects (8) The Design Of IEnumerable [ LINQ via C# series ] Currently in .NET, iterator pattern is implemented via IEnumerable and IEnumerator (or IEnumerable and IEnumerator): namespace System.Collections { // Represents a collection which can be iterated. public interface... Understanding LINQ to SQL (1) Object-Relational Mapping [ LINQ via C# series ] According to Wikipedia , Object-relational mapping is: a programming technique for converting data between incompatible type systems in relational databases and object-oriented programming languages. This is the LINQ to SQL sample...Understanding LINQ to SQL (2) IQueryable [ LINQ via C# series ] The core of LINQ to Objects is IEnumerable: Query methods are designed for IEnumerable as extension methods , like Where(), Select(), etc.; Query methods are designed to be fluent, LINQ to Objects queries can be...Understanding LINQ to SQL (3) Expression Tree [ LINQ via C# series ] In LINQ to Objects, lamda expressions are used everywhere as anonymous method, like Where(): public static IEnumerable Where( this IEnumerable source, Func predicate...Understanding LINQ to SQL (4) Data Retrieving Via Query Methods [ LINQ via C# series ] After understanding: object model generating from SQL Server schema query method chaining on IQueryable SQL are translated from expression tree, which is required by IQueryable now it is time to take a deeper look...Understanding LINQ to SQL (5) Remote And Local Method Call [ LINQ via C# series ] Since LINQ to SQL is translating C# methods into SQL, all the C# methods are required to make sense in SQL. According to MSDN : A local method call is one that is executed within the object model. A remote method call is one that...Understanding LINQ to SQL (6) Working With Deferred Execution [ LINQ via C# series ] Similar with LINQ to Objects, LINQ to SQL supports deferred execution when possible. For example: using ( NorthwindDataContext database = new NorthwindDataContext ()) { IQueryable < Category > source = database.Categories;...Understanding LINQ to SQL (7) Data Changing [ LINQ via C# series ] After understanding how to retrieve data with LINQ to SQL, now take a look at data change (create (insert) / update / delete). Object Identity When changing data queried by LINQ to SQL, one common confusion for LINQ to SQL beginners...Understanding LINQ to SQL (8) Transaction [ LINQ via C# series ] Database data Changing cannot be talked about without transactions . Implementing TRANSACTION (BEGIN / COMMIT / ROLLBACK) The previous post has shown that, when invoking SubmitChanges(), the translated SQL (INSERT / UPDATE / DELETE...Understanding LINQ to SQL (9) Concurrent Conflict [ LINQ via C# series ] Conflicts are very common when concurrently accessing the same data. Conflicts in concurrent data access The following code presents the concurrent conflict scenario: Action < int , Action < Category >> updateCategory...Understanding LINQ to SQL (10) Implementing LINQ to SQL Provider [ LINQ via C# series ] So far LINQ to SQL data CRUD (Creating / Retrieving / Updating / Deleting) has been explained. This post takes a deeper look at the internal implementation of LINQ to SQL query. The provider model Unlike IEnumerable / IEnumerable...Understanding LINQ to SQL (11) Performance [ LINQ via C# series ] LINQ to SQL has a lot of great features like strong typing query compilation deferred execution declarative paradigm etc., which are very productive. Of course, these cannot be free, and one price is the performance. O/R mapping... 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Cocoa 使用了一种修改版本的MVC模式来处理GUI的显示。MVC模式(自1979年以来)已经出现很长时间了,它皆在分离显示用户界面所需的大量任务,并处理用户交互。正如名称所蕴含的,MVC具有三个主要部分,Model(模型)、View(视图)和Controller(控制器): 模型——模型是特定于领域的数据表现形式。比如说,我们正在创建一个任务列表应用程序。你可能会有一个Task对象的集合,书写为List。 你或许把这些数据保存在数据库、XML文件,或者甚至从Web Service中得到,不过MVC不那么关心它们是在何处/如何来持久保存的(乃至它们是什么)。相反,它特别专注于如何显示这些数据,并处理与用户交互的,好的模型类不包括任何有关用户界面的内容,可以在多个应用程序中使用。视图——视图代表了数据如何实际地显示出来。在我们这个假设的任务应用程序中,会在一个网页(以HTML的方式)中来显示这些任务,也会在一个WPF页面中(以XAML的方式)来显示,或者在一个iPhone应用程序中显示为UITableView 。如果用户点击某个任务,要删除之,那么视图通常会触发一个事件,或对Controller(控制器)进行一个回调,好的视图类是通用类,可以在多个应用中使用。控制器——控制器是模型和视图间的粘合剂,负责控制整个应用的流程。控制器的目的就是获取模型中的数据,告知视图来显示。控制器还侦听着视图的事件,在用户选中一个任务来删除的时候,控制着任务从模型中删除。通过分离显示数据、持久化数据和处理用户交互的职责,MVC模式有助于创建易于理解的代码。而且,它促进了视图和模型的解耦,以便模型能被重用。例如,在你的应用程序中,有两个界面,基于Web的和WPF的,那么你可以在两者中都使用同样的模型定义代码。 因而,在很多MVC框架中不管具体的工作方式如何,基本原理都大致如此的。然而,在Cocoa(及Cocoa Touch)中,还是或多或少有所不同,苹果用MVC来代表Views(视图)、View Controller(视图控制器)和Models(模型);但是在不同的控件中,它们却不是完全一致的,实现的方式也不太一样。 在Objective-C/Cocoa的世界里,我们建立的controller通常是指应用程序(Application)的委托(Delegate),或者可以简单称做app delegate。当你在Objective-C里面建立一个app delegate的时候,这个delegate可以做为你所有model和view的controller,或者你也可以为不同的model和view分别创建controller。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Webbench是知名的网站压力测试工具,它是由Lionbridge公司(http://www.lionbridge.com)开发。Webbench能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。webbench的标准测试可以向我们展示服务器的两项内容:每秒钟相应请求数和每秒钟传输数据量。webbench不但能具有便准静态页面的测试能力,还能对动态页面(ASP,PHP,JAVA,CGI)进 行测试的能力。还有就是他支持对含有SSL的安全网站例如电子商务网站进行静态或动态的性能测试。 Webbench最多可以模拟3万个并发连接去测试网站的负载能力。 官方主页:http://home.tiscali.cz/~cz210552/webbench.html 官方介绍: Web Bench is very simple tool for benchmarking WWW or proxy servers. Uses fork() for simulating multiple clients and can use HTTP/0.9-HTTP/1.1 requests. This benchmark is not very realistic, but it can test if your HTTPD can realy handle that many clients at once (try to run some CGIs) without taking your machine down. Displays pages/min and bytes/sec. Can be used in more aggressive mode with -f switch. 具体可以参考以下几篇文章有很详细的介绍: 找到一款不错的网站压力测试工具webbench[原创]Web性能压力测试工具之WebBench详解实战网站压力/负载测试之WebBench篇下面贴几个6J1LQ320FOZZ8GBRDRX[9WL测试Jexus 5.2.4处理静态网页和ASP.NET网页的速度的压力测试数据: 测试环境,Webbench与Jexus在同一服务器。 CPU:1个/4核,速度2GHz 内存:4G Linux:Ubuntu V10.04 64位服务器版,内核3.2.0 测试软件:Webbench v1.5 mono版本:3.0.6 Jexus版本:5.2.4 工作进程数:1个 静态文件:107字节 ASPX文件:145字节,无运算逻辑和数据处理。 ZHP9$XU}WPTJT$(YG{08NV4 QYH3~WY]B$4_}FYV@%5SY5E 63NB({5ACTHKAKD1$)GQNMC }YGHL0)$$%MC485[6FF2Z]N 2B)J8_IKSWI89F9KE)3SMR7 VQB4({RAHJ4SEV[43~Y78UU 测试数据表明,在无错情况下: 1、两个软件都很快,Nginx比Jexus更快一点; 2、Jexus更稳定,大并发下表现更好; 3、在实际应用中,Jeuxs更强,因为真正的WEB应用还会有ASP.NET之类的运算逻辑,而这刚好是Jexus的强项。 另外,由于多个第三方测试表明Jexus静态处理速度超过IIS7/8 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
默认情况下,AppFabric缓存提供了两种配置存储:一个SQL Server存储和XML文件存储。该解决方案提供和供AppFabric缓存自定义配置提供程序,使用Amazon S3存储缓存的配置。 您可以创建您通过实现IDataStoreProxy接口和注入新的实施将自己的数据存储TransactionContext 看看现有AmazonProxy指导。 该解决方案包含4个项目 一个WinForms可执行项目,创建自定义配置AppFabric向导的UI一个库,它包含了ICustomProvider定制实现,它使用亚马逊的S3的配置存储(而不是SQL数据库或共享文件夹)一些轻量的测试的测试项目部署项目将配置所有必要的注册表项,并把可执行文件和库放入相应的文件夹。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Mono,作为.NET运行库的开源实现,正在将微软的技术带到未曾预料到的地方,包括iPhone,Android和Wii。 根据Novell公司的首席Mono开发者Miguel de Icaza称,Apple的App Store中有多个应用程序是基于Mono。 这可能会让那些熟悉苹果应用程序限制政策的人感到意外,因为苹果公司严格禁止开发者使用解释语言和第三方运行环境——在很大程度上就将.NET和Java之类技术排除在外。 静态编译(Static compilation)是一道特别的沙司,正是它使得Mono在iPhone中运行成为可能。Mono还允许开发者使用ahead-of-time(AOT)编译,它能将.NET的通用中间语言(CIL)直接在编译中转变成原生码,这意味着应用程序不必要使用运行时编译执行技术(JIT),以在运行时产生原生码。de Icaza提到,开发者还开始使用Unity,基于Mono的开发3D游戏的第三方商业编程框架。 目前App Store中大约40款应用程序是基于Unity和Mono。一个Wii上的德国游戏My Animal Center,代码主要是C#,用Unity和Mono开发。除了iPhone和Wii之外,一位开发者正试验性的将Mono运行库移植到Android平台。这一切都展示了开源的价值和内在的适应性。 Mono是一个开源的跨平台的.NET运行环境,支持Unix, Windows, MacOS等操作系统。 Mono 2.10是基于mono在github上的主分支Mono 2.8的一个重要升级,发布于2011年2月15日。 Mono 2.10主要更新和改进: Google Native Client Support 支持Google本地客户端,允许本地代码在浏览器中运行。Mono虚拟机,垃圾收集器和Just-in-Time编译器可以运行于本地客户端的沙箱中。New Profiler engine 新版Profiler解决了原先的Profiler在处理多线程、multi-appdomain应用程序以及大数据量时的诸多问题,GC新增的触发事件让开发者可以针对自己的程序编写更先进的profiling工具和GC tracking工具。Faster socket stack 更快的socket堆栈,Socket异步操作直接发送至IO池,节约了内存和CPU时间。SocketAsyncEventArgs支持每个操作使用一个线程。Improved Parallel Framework 增加的并行框架。SGen Precise Stack Scanning and Many performance improvements. SGen(mono的垃圾收集器)的精确堆栈扫描和性能增强,欲更多了解SGen,请阅读这里。Unified MonoTouch/Monodroid runtime support 统一的MonoTouch/Monodroid运行时支持。Cecil/Light Cecil是一个可以生成ECMA CIL的类库(有点类似于.NET中的Reflector),可以用它加载存在的程序集,浏览其中的类型,修改其中的代码,并将修改后的代码保存至程序集中。New C# Compiler backend (can now use any custom mscorlib) 新的C#后台编译器,基于 IKVM.Reflection API ,允许开发者引用第三方的mscorlib.dll、或者自己定制的mscorlib.dll、或者来自其他项目的(比如:微软的MicroFramework)。下一版本的mono,batch compilers (gmcs, smcs与dmcs)将全部切换至IKVM.Reflection。VB Compiler can now compile to both 2.0 and 4.0 profiles. VB编译器用cecil/light取代原来的Reflection,这样可以通过一个编译器生成使用不同版本运行时的程序集。Supports ASP.NET MVC3, Razor and new WebPages. 支持ASP.NET MVC 3, Razor, WebPages。虽然ASP.NET MVC 3是开源的,但它依赖一些非开源的类库,而且这些类库并不是.NET Framework的一部分。Mono中没有这些类库的开源实现,所以ASP.NET MVC 3应用程序不能无缝地运行于mono,你需要移除对Microsoft.Web.Infrastructure.dll的引用,使用mono自己的实现。Razor与WebPages可以直接使用微软.NET的程序集运行于mono。New WebMatrix.Data database API. 微软WebMatrix.Data的mono实现。通过这个API,可以利用C# 4.0的动态特性编写数据库访问代码(代码示例)。欲了解更多WebMatrix.Data, 推荐阅读re-introducing WebMatrix.Data。Improved OSX Mono 提供了一些OSX Mono的更新。F# and IronRuby 从Mono 2.10开始,将F#编译器和工具打包进来。在Linux安装包和Mac安装器中包含了IronRuby 和IronPython。其他改进: Winforms bug fixesUpdates to msbuildImproved Moonlight support, and faster build times for MoonlightWCF:System.ServiceModel.DiscoveryWCF 4.0-style configurationASP.NET 4.0:BaseMenuRendererSytem.Xaml: significant improvements on serialization of complex types and properties in .NET compatible format. Now it can be built on mobile profiles.More 4.0 APIs implementedVersion tolerant serializationC# 4.0 significantly improved based on the Microsoft test suites for Silverlight 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
使用Topshelf创建Windows 服务简要的介绍了创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的介绍使用使用Topshelf创建Windows 服务。Topshelf是一个开源的跨平台的宿主服务框架,支持Windows和Mono,只需要几行代码就可以构建一个很方便使用的服务宿主。 1、Topshelf的代码托管在http://topshelf-project.com/,可以在这里下载到最新的代码。 2、使用Visual Studio创建一个控制台应用程序引用程序集TopShelf.dll 合log4net.dll 。 3、创建一个简单的服务类,里面包含两个方法Start和Stop,这个服务只是演示代码,所以我们每隔5秒输出一个日志。 using System; using System.Timers; using log4net; namespace SampleWindowsService { public class SampleService { private Timer _timer = null; readonly ILog _log = LogManager.GetLogger(typeof(SampleService)); public SampleService() { double interval = 5000; _timer = new Timer(interval); _timer.Elapsed += new ElapsedEventHandler(OnTick); } protected virtual void OnTick(object sender, ElapsedEventArgs e) { _log.Debug("Tick:" + DateTime.Now.ToLongTimeString()); } public void Start() { _log.Info("SampleService is Started"); _timer.AutoReset = true; _timer.Enabled = true; _timer.Start(); } public void Stop() { _log.Info("SampleService is Stopped"); _timer.AutoReset = false; _timer.Enabled = false; } } } 4、在Main方法中使用Topshelf宿主我们的服务,主要是告诉Topshelf如何设置我们的服务的配置和启动和停止的时候的方法调用。 using System.IO; using log4net.Config; using Topshelf; namespace SampleWindowsService { class Program { static void Main(string[] args) { XmlConfigurator.ConfigureAndWatch( new FileInfo(".\\log4net.config")); var host = HostFactory.New(x => { x.EnableDashboard(); x.Service<SampleService>(s => { s.SetServiceName("SampleService"); s.ConstructUsing(name => new SampleService()); s.WhenStarted(tc => { XmlConfigurator.ConfigureAndWatch( new FileInfo(".\\log4net.config")); tc.Start(); }); s.WhenStopped(tc => tc.Stop()); }); x.RunAsLocalSystem(); x.SetDescription("SampleService Description"); x.SetDisplayName("SampleService"); x.SetServiceName("SampleService"); }); host.Run(); } } } 4、配置Log4net和运行我们的服务,服务可以当作控制台来运行,这在开发的时候是非常方便的。服务的安装很方便SampleWindowsService.exe install安装成功后,可以通过服务控制台启动,或者也可以通过一下命令运行SampleWindowsService.exe start服务的卸载方法也非常简单了SampleWindowsService.exe uninstall 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
开源可不仅仅是将代码扔到网上就万事大吉了,将开源项目变成能让自己引以为豪的东西才算成功。那么,你需要注意哪些方面呢? 写好指导性文字 每一个开源项目有三样东西是少不了的:项目目标和方法的简要说明、如何参与和授权许可。最好把它们预先放在一个README文件里。 我还喜欢加入一个名为“组织和理念”的部分,概括项目如何构成,各个东西都在哪儿,代码是怎样写的,需要哪些类型的测试,性能与简洁性怎么平衡。(详见案例unstdlib.py) 接下来是“贡献”部分,要说清楚开发者怎样开始参与项目,以及将代码成功合并进项目的所有步骤。urllib3的贡献部分,已经被其他好几个项目采用了。 查看还没有解决的问题,或者新开一个问题来讨论某个功能设想或bug。把urllib3库添加到Github上开始进行更改。编写测试来显示这个bug是固定的或者它的功能是否正如预料的那样运行。发送一个pull请求,干扰保持器,直到它被合并到一起并发布。最后,每一个开源项目需要有一个授权许可,如果没有许可,那就意味着版权属于开发者,其他人需要明确的许可才能使用。 态度 对待用户和贡献者有好的态度是至关重要的,偶尔会有类库用户误闯到你的问题跟踪器里,并且很愚蠢的在文档编制里写了命令。那该怎么办? 1.你可能会斥责用户,因为他们的鲁莽行为浪费了你很多时间。 2.你也可以耐心的向用户解释他们所误解的,一旦他们进一步理解问题,那么邀请他们发送一个pull请求为其他用户改善文件编制。 有些团队可能因为某些原因选择第一种态度,也许是因为他们觉得维护人员做的是一件吃力不讨好的工作,还要承担丢失贡献者的责任。不过先来检查一下这两种态度所带来的效果。 当你责怪用户的时候,毫无疑问会丢失用户,还意味着丢失了他成为你的贡献者的可能性,说不定这种影响会传播到其他人那里,一传十十传百,别人可能真的认为你的文件编制里有问题。这无异于搬石头砸自己的脚。 但只要你有足够的耐性,礼貌待人,鼓励他们为项目出力,他们就会很有斗志。说不定他们就能在项目上做出重大影响,彻底改变现状。 在工作中保持良好的态度可能是比较难的一部分,因为每个维护人员的情况是不一样的,但是,礼貌、积极和进步是至关重要的。不仅仅是对于你和项目,还有整个团队。 营销 也许你能写出最有用最完美的代码并实现代码运行,但是你对技术社区的贡献会因为你允许人们重复使用你的代码而无限放大。 找到你的项目,站在SEO的位置思考整个项目,为项目选取一个带有重要关键词的相关名称。README里的项目描述和第一段应该是项目的简单总结,里面所有的重要关键词都是之前人们所搜索的。 urllib3——带有线程安全连接池的Python HTTP类库,支持文件公布,智能友好等等。 Python,HTTP类库,线程安全,连接池,文件公布,这些都是当人们遇到要使用Python的标准HTTP类库(urllib、urllib2、httplib)的时候所需要的。 一旦准备好了README,就要确保能够生成一些文档。发布在Read the Docs将是一个很好的选择。包括一些代码样本和便于采纳的详细菜单。 为你的受众提供技术支持,建立一些StackOverflow警报过滤器,甚至可以过滤掉谷歌的奇怪论坛警报。如果你推自己的软件,这个警报会帮助你添加一个你就是开发者的免责声明。 考虑合作关系,为框架编写一个可以使用你自己工具的插件,并观察这些工具能否将框架连接到README。两年前,我和Kenneth Reitz在不同的场合进行交谈之后,我们决定合作。虽然urllib3已经是非常流行的Requests类库的核心,但远远落后于当时的httplib2。当我和Kenneth Reitz合作之后,我们两个团队的成果远超出了我们的想象。此时,在我们的合作之间建立明确的规则和界线是非常重要的,这个规则后来也帮我们在合作当中建立了深厚的友谊和相互尊重打下了基础。 充足的时间,我的一个比较受欢迎的项目花了至少一年的时间。这在营销人员看来是懒散的表现,但如果你按照文章里说的那样去做,正确的完成每一件事,那么营销人员会不请自来。 技术社区 想要一个人做完所有的事是很难的,特别是很多人都期待着你能拿出好的作品。 抓住任何一个机会寻找pull请求。集思广益的力量是无穷大的,所以无论何时何地我都会向技术社区的成员寻求意见,他们常常说的RFC我从来没听过,甚至有的时候他们会主动研究前端主题。 大胆寻求帮助,我本打算花数小时致力于开源工作,但有时候日程安排忽略了或是我忘记了关于pull需求。我鼓励人们参与并在我需要更多的人参与的时候提醒我。在更复杂的分支,它有助于要求志愿者代替维护人员来处理这个问题,直到它准备好合并。 尽可能的自动化,去年,我们为urllib3设置了100%的测试覆盖规则,这使得我们的项目维护更加简单。任何功能都必须经过测试,否则它可以在没有通知的情况下被删除。这意味着每一个pull请求必须在合并之前完全测试。 维护贡献者列表,提醒并邀请贡献者把他们自己添加到列表里,即使他们做的事情微不足道。几个字节的存储库不花费你任何东西,这和他们因得到认可而产生的自豪感是无法比拟的。 找到乐趣 Andrey Petrov从事与HTTP和urllib3相关的的工作已经数年了,但仍然坚持维护开源项目,因为他喜欢技术社区,并在开源项目中感觉到自豪。他最后强调,工作中尽最大的努力,并为自己的工作而骄傲,有些人可能会欣赏你,有些人却不会。最后总会有人感激你为开源社区所做的积极有效的贡献。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
WCF Data Service工具包是一组WCF Data Service(OData的.NET实现),目的是使更容易地构建WCF Data Service,支持数据的任何存储上的OData服务而不需要深入的理解Linq,当然了,深入的理解Linq的非常必要的。 它诞生于现实的一些服务,诸如Netflix, eBay, Facebook, Twitpic等等公司的公开的服务,这个工具包已经在现有的产品中使用,被证明解决了一些有趣的问题,而且在工作中发挥了很大的作用。 在使用这个工具包之前需要知道这个工具用来解决什么问题,你应该是寻找一个暴露非关系数据库存储的数据(EF+ WCF 数据服务可以完美的解决关系数据库存储的数据),当我们说数据存储的时候指的是什么呢,你可能会想到下面的场景: 一个XML文件(或文件)现有的Web API(或APIs)一个遗留数据库,你要重新塑造大幅而不想暴露数据库结构专有软件系统,提供了一个时髦的一次性它的数据格式云数据库(例如SQL Server)和NoSQL(例如Windows Azure的表存储)A CSV file zipped together with a MySQL databaseA SOAP API combined with an in-memory cacheA parchment scroll infused with Egyptian hieroglyphics该工具包还提供了每个现实世界的OData Service都需要面对的共同任务,你得到JSONP形式的支持,输出缓存,URL sanitization等等,所有的开箱即用。可以在这里下载或者通过NuGet 下载,查询“WCFDataServicesToolkit” 这个ID。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
应用web化,不论对开发商,还是对用户来说,实在是一种很经济的选择,因为基于web的应用,客户端的规则很简单,容易学习,容易维护,容易发布。但对程序员来说,因为浏览器的局限性,却要面对很多挑战。怎么样来进行基于web的套打,就是这么一个令多数程序员头痛不已的问题。 基于web的套打,难度在于要将浏览器中呈现的html,精确地打印到票据中,而且能够实现对分页位置的控制。下面就ie浏览器所能采用的套打解决方案,来个汇总分析,希望对大家有所帮助。 jatoolsPrinter 是一款实现网页套打的免费工具。该工具的特点是可以直接对web页面进行精确的分页打印,这不仅使“会设计网页就会做网页套打”成为可能,也使项目经理们摆脱了预算紧张的压力。jatoolsPrinter通过在网页中嵌入控件,解决了web客户端精确打印,批量打印,打印配置自动保留等问题。jatoolsPrinter 官方正式免费版,支持ie6+,http://printfree.jatools.com。 功能特点: 真正免费,不加水印,没有ip或域名限制,不限时间,兼容ie6+ 无须注册,下载即用 提供经过微软数字签名的cab自动安装包,安装更方便 长期升级保障,免费论坛支持,让你无后顾之忧 稳定可靠,启动速度远胜同类产品 常用功能集于一身,简约而不简单,软件大小只有84k 本文主要介绍jatoolsPrinter打印控件来完成web的打印功能,这个控件已经把打印功能封装的非常好,主要是把这个控件引入,之后写一些简单的js代码就能完成相应的打印功能。 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <!-- 插入打印控件 --> <object id="jatoolsPrinter" classid="CLSID:B43D3361-D075-4BE2-87FE-057188254255" codebase="jatoolsPrinter.cab#version=5,7,0,0"> </object> <script type="text/javascript"> function doPrint(how) { //打印文档对象 var myDoc = { documents: document, // 打印页面(div)们在本文档中 copyrights: '杰创软件拥有版权 www.jatools.com' // 版权声明必须 }; // 调用打印方法 if (how == '打印预览...') jatoolsPrinter.printPreview(myDoc); // 打印预览 else if (how == '打印...') jatoolsPrinter.print(myDoc, true); // 打印前弹出打印设置对话框 else jatoolsPrinter.print(myDoc, false); // 不弹出对话框打印 } </script> </head> <body> <form id="form1" runat="server"> <div id='page1' style='width:300px;height:300px;'> test </div> <input type="button" value="打印预览..." onclick="doPrint('打印预览...')"/> <input type="button" value="打印..." onclick="doPrint('打印...')"/> <input type="button" value="打印" onclick="doPrint('打印')"/> </form> </body> </html> 主要分几个步骤: 一、引入打印控件jatoolsPrinter <!-- 插入打印控件 --> <object id="jatoolsPrinter" classid="CLSID:B43D3361-D075-4BE2-87FE-057188254255" codebase="jatoolsPrinter.cab#version=5,7,0,0"> </object> 二、给要打印的div取id名 三、编写js代码实现打印div的功能 (注意:在同一页面中,有多个可打印文档,他们可以用page_div_prefix属性来区别page_div_prefix前缀+page+页序号 构成可打印div的id,如前缀为 'report1' ,则找到以 'report1page1'为id的div作为文档首页该属性,默认值为空) 注意事项: 控件在打印指定div对象时,如果纸张太小不够打印时,超出部分将被截掉(clip)。 被指定的div中的内容,可以是html任何可见对象,图片,flash,或文本等等。 控件打印时,边距可设,不设则取打印机默认值。 div的id必须连续,如果你的div,存在 'page1'、'page2'、'page4',而不存在'page3',则控件只打印前两页,'page4'不会被打印。 div对象在页面中的位置,可以是随意的,比如,page1显示在page2后面,也是合法的。 指定的div会被打印,没被指定的html元素将不会被打印,比如,本示例中的‘打印’按钮,不会被打印。 copyrights属性是版权信息,必须写。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
很多的api,例如GitHub’s API 都有流量控制的做法。使用速率限制,以防止在很短的时间量客户端向你的api发出太多的请求.例如,我们可以限制匿名API客户端每小时最多60个请求,而我们可以让更多的经过认证的客户端发出更多的请求。那么asp.net webapi如何实现这样的功能呢?在项目WebApiContrib 上面已经有了一个实现:https://github.com/WebApiContrib/WebAPIContrib/blob/master/src/WebApiContrib/MessageHandlers/ThrottlingHandler.cs ,具有良好的可扩展性。 最简单的方法是使用ThrottlingHandler注册使用简单的参数,例如控制每个用户每小时60个请求: config.MessageHandlers.Add(new ThrottlingHandler( new InMemoryThrottleStore(), id => 60, TimeSpan.FromHours(1))); IThrottleStore接口 使用ID +当前的请求数量。InMemoryThrottleStore 只有一个内存中存储,但你可以轻松地扩展实现为分布式缓存或数据库。还可以轻松地自定义ThrottlingHandler的行为,例如我们针对一个ip地址可以更好的进行控制。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
1、LINQ to SQL集成到应用程序中需考虑的一个问题, 到底应该返回IQueryable<T>还是IQueryable? 或许这个列表还应该继续扩展为T, List<T>, 对于Business Layer来说, 到底应该选择哪一种? 2、需要一个分页功能; 到这一步的时候我又有几个选择, 利用LINQ to SQL可以执行自定义存储过程的功能, 完全自己写, LINQ to SQL本身已经有API提供了分页功能了,不过只有排序或包含标识列的查询中支持Skip方法, 我有什么理由放弃, 除非性能真的到了非常Critical的时候, 看看下面的分页API, 多么简单: return q.Skip<Order>((currentPage - 1) * pageSize).Take< Order >(pageSize) 生成的T-SQL语句: SELECT [t2].[OrderID], [t2].[OrderNumber], [t2].[OrderName], [t2].[DateSubmitted], [t2].[SubmittedBy], ([t2].[LastName] + @p2) + [t2].[FirstName] AS [SubmittedUserName]FROM (SELECT TOP (10) [t0].[OrderID], [t0].[OrderNumber], [t0].[OrderName], [t0].[SubmittedBy], [t0].[DateSubmitted], [t1].[FirstName], [t1].[LastName]FROM [dbo].[Order] AS [t0]INNER JOIN [dbo].[Users] AS [t1] ON [t1].[UserID] = [t0].[SubmittedBy]WHERE ([t0].[NextProcessedBy] = @p0) AND ([t0].[CurrentState] = @p1)) AS [t2]– @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [jlv]– @p1: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [New]– @p2: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [, ] DLINQ生成的SQL语句是利用TOP和嵌套子查询, 这种方法已经被证明是比较高效的做法(相比于临时表的做法), 所以完全有理由可以一试.到这里, List, IQueryable, IQueryable都没有任何问题.3、需要一个动态排序功能, 这里List的局限性出来了, 传统的做法可能需要用一个dynamic参数来传递需要排序的列然后到SP当中来执行, 但我们已经不打算使用SP了, 也没有动态sql语句, 所有的东西都是强类型的, 然后有LINQ to SQL在运行时来帮我们转换为T-SQL语句。首先List的话, 我们不知道到底哪个字段要排序, 如果使用字符串作为参数的话, 例如放一个string sortBy作为方法的参数, 那么在方法体内就需要做if…else或者switch的判断, 而且还要考虑倒序还是正序的排序要求, 而且你还要hard code,很明显麻烦来了.然而如果使用IQueryable却可以很好的解决所有的这些问题. 但是IQueryable不能跨assembly, 一旦跨了assembly的话, 你无法使用var来引用匿名类里面的property, 绑定到control是没有问题的, 但是客户端的动态查询却成了问题, 因为你根本不知道匿名类是什么. 那么选择IQueryable<T>, 我们选择返回IQueryable<T>给客户端, 分页/排序都没有任何问题. 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
类似于Sql Management studio一个用于Linq语法的工具LINQPad。LINQPad lets you interactively query SQL databases in a modern query language: LINQ. Kiss goodbye to SQL Management Studio! LINQPad supports everything in C# 3.0 and Framework 3.5:LINQ to SQL LINQ to ObjectsLINQ to XMLLINQPad is also a terrific tool for learning LINQ: it comes preloaded with 200 examples from the recently released C# 3.0 in a Nutshell. There's no better way to experience the coolness of LINQ and functional programming. LINQPad is free and needs no installation: just download and run. The executable is only 1MB and is self-updating. 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Bruce Eckel(著有多部编程书籍)和Jonas Boner(Akka的缔造者和Typesafe的CTO)发表了“反应性宣言”,在其中尝试着定义什么是反应性应用。 这样的应用应该能够: 对事件做出反应:事件驱动的本质,让反应性应用能够支持文中提到的若干特性。对负载做出反应:聚焦于可扩展性,而不是单用户性能。对失败做出反应:建立弹性系统,能够从各个层级进行恢复。对用户做出反应:综合上述特征,实现交互式用户体验。在这份宣言公布之后,Scala的创造者Martin Odersky、Reactive Extensions的创造者Erik Meijer和Akka科技公司的领导者Roland Kuhn,在Coursera上发布了一套免费课程,名为“反应性编程原理”: 该课程的目标在于讲授反应性编程的原理。反应性编程是一门新兴的学科,结合了并发、事件驱动和异步系统。对于编写任何类型的Web服务或分布式系统来说,它都至关重要;同时它在众多高性能并发系统中占有核心位置。反应性变成可以被视作高阶函数式编程对并发系统的自然拓展,通过协调和编排Actor交换的异步数据流,来处理分布的状态。 Reactive Extensions(Rx)的优点在于能够将传统的异步编程方式从支离破碎的代码调用中解放出来。Rx能够使的我们可以将异步代码写到一个单独的方法中,使得代码可读性和可维护性大大增强。 《Reactive Extensions介绍》我们了解了Rx中的一些比较重要的操作符,本文中我们将会学习如何将Reactive Extensions(Rx)应用到我们的应用程序中。 同步方法调用是阻塞式的,在很多场景下这是不合适的。我们能够用Rx改造成异步调用。一个最简单的方法就是使用IObservable.Start方法,使得Rx为我们来管理这些异步调用。 public static void ObservableStart(int x, int y) { PlusTwoNumberAsync(x, y).Subscribe(Console.WriteLine); Console.ReadKey(); } private static IObservable<int> PlusTwoNumberAsync(int x, int y) { return Observable.Start(() => PlusTwoNumber(x, y)); } private static int PlusTwoNumber(int x, int y) { Thread.Sleep(5000); return x + y; } 除了Observable.Start外也可以使用Observable.Return来将同步方法改造为异步方法。只需要将上面的PlusTwoNumberAsync方法改为下面即可,运行程序的效果相同。 private static IObservable<int> PlusTwoNumberReturnAsync(int x, int y) { return Observable.Return(PlusTwoNumber(x, y)); } 使用SelectMany可以很方便的实现诸如在一个异步方法中调用另外一个异步方法的功能。 public static void ObservableSelectMany(int x, int y) { PlusTwoNumberStartAsync(x, y).SelectMany(aPlusB => MultiplyByFiveAsync(aPlusB)).Subscribe(Console.WriteLine); } private static IObservable<int> MultiplyByFiveAsync(int x) { return Observable.Return(MultiplyByFive(x)); } private static int MultiplyByFive(int x) { Thread.Sleep(5000); return x * 5; } 完整代码如下: // ----------------------------------------------------------------------- // <copyright file="RxAsyncCall.cs" company=""> // TODO: Update copyright text. // </copyright> // ----------------------------------------------------------------------- namespace RxPractice { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reactive.Linq; using System.Threading; /// <summary> /// 异步调用 /// </summary> public class RxAsyncCall { public static void ObservableStart(int x, int y) { PlusTwoNumberStartAsync(x, y).Subscribe(Console.WriteLine); } public static void ObservableReturn(int x, int y) { PlusTwoNumberReturnAsync(x, y).Subscribe(Console.WriteLine); } public static void ObservableSelectMany(int x, int y) { PlusTwoNumberStartAsync(x, y).SelectMany(aPlusB => MultiplyByFiveAsync(aPlusB)).Subscribe(Console.WriteLine); } private static IObservable<int> PlusTwoNumberStartAsync(int x, int y) { return Observable.Start(() => PlusTwoNumber(x, y)); } private static int PlusTwoNumber(int x, int y) { Thread.Sleep(2000); return x + y; } private static IObservable<int> MultiplyByFiveAsync(int x) { return Observable.Return(MultiplyByFive(x)); } private static int MultiplyByFive(int x) { Thread.Sleep(5000); return x * 5; } private static IObservable<int> PlusTwoNumberReturnAsync(int x, int y) { return Observable.Return(PlusTwoNumber(x, y)); } } } Implementing the GeoCoordinateWatcher as a Reactive Service Using Reactive Extensions for Streaming Data from Database Bing it on, Reactive Extensions! – Story, code and slides IntroToRx.com is the online resource for getting started with the Reactive Extensions to .Net http://rxdemo.codeplex.com/ http://blog.csdn.net/fangxinggood/article/details/7381619 Reactive Programming For .NET And C# Developers - An Introduction To IEnumerable, IQueryable, IObservable & IQbservable 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
工具Console2是Windows操作系统的系统命令cmd的扩展软件。它的最大好处是支持多标签,这样一个窗口就有多个标签来在不同的目录下执行命令,而且不会在任务栏里产生过多的窗口。项目网站说明:“Console is a Windows console window enhancement. Console features include: multiple tabs, text editor-like text selection, different background types, alpha and color-key transparency, configurable font, different window styles.”配置说明:“菜单”—>Edit—>Setting...—>Behavior—>选择“Copy on select”“菜单”—>Edit—>Setting...—>Mouse—>Paste text—>Right“菜单”—>Edit—>Setting...—>Mouse—>Context menu text—>Right+Shift“菜单”—>View—>Console Windows—>属性—>字体—>新宋体—>确定—>选择“保存属性...”—>确定—>Alt+F4Console2首页:http://sourceforge.net/projects/console 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
作为下一代 ADO.NET 3.0 的开发框架,Entity Framework 让我们从复杂的关系数据模型中解脱出来,使用更加符合面向对象的实体数据模型(Entity Data Model)来完成业务设计和开发。Entity Framework 很像 NHibernate,同样采取 XML 进行映射。不过借助于强大的可视化设计工具和向导,我们可以非常方便地完成这些头疼的工作。 Entity Framework 对 Linq 的直接支持 —— LINQ to EntitiesEntity Framework Features: Entity DesignerGenerate a model from a database (via wizard) and display it on the designer surface Edit conceptual model properties (namespace, alias, etc.)Control visual aspects of the design surface (layout) and persist changesAdd, Delete, and Edit Entities; Scalar properties; Associations; and InheritanceAutomatic set managementAutomatic Navigation property managementError reportingValidate model and mappings using Entity Framework Runtime Entity MappingView the mapping for a C-Side Entity or Association Rename or delete C-Side objects without worrying about mappingMap an EntityType to multiple tablesApply multiple conditions to a table mappingMap associationsAutomatic generation of conditions and referential constraints on associationsTPH: Map an Entity hierarchy to a single tableTPT: Map an Entity hierarchy to multiple tables Entity Model BrowserUnderstand and visualize the model in a tree hierarchy Visually relate shapes on the designer surface with hierarchy in model Visual Studio IntegrationSupport for C# and VB in multiple project types: ASP.NET Web site, ASP.NET Web Application Project, Console, WinForms, and Library Project system integration: item template for .edmx file, model generation wizard, EdmxDeploy.exe, and Entity Framework validation on buildSupport for multiple Visual Studio editions: Express, Standard, Pro, and VSTS.ADO.NET team blog 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
一、 PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃、断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统库是MyISAM的,相比之下,PG数据库这方面要好一些。二、任何系统都有它的性能极限,在高并发读写,负载逼近极限下,PG的性能指标仍可以维持双曲线甚至对数曲线,到顶峰之后不再下降,而 MySQL 明显出现一个波峰后下滑(5.5版本之后,在企业级版本中有个插件可以改善很多,不过需要付费)。三、PG 多年来在 GIS 领域处于优势地位,因为它有丰富的几何类型,实际上不止几何类型,PG有大量字典、数组、bitmap 等数据类型,相比之下mysql就差很多,instagram就是因为PG的空间数据库扩展POSTGIS远远强于MYSQL的my spatial而采用PGSQL的。 四、PG 的“无锁定”特性非常突出,甚至包括 vacuum 这样的整理数据空间的操作,这个和PGSQL的MVCC实现有关系。五、PG 的可以使用函数和条件索引,这使得PG数据库的调优非常灵活,mysql就没有这个功能,条件索引在web应用中很重要。六、PG有极其强悍的 SQL 编程能力(9.x 图灵完备,支持递归!),有非常丰富的统计函数和统计语法支持,比如分析函数(ORACLE的叫法,PG里叫window函数),还可以用多种语言来写存储过程,对于R的支持也很好。这一点上MYSQL就差的很远,很多分析功能都不支持,腾讯内部数据存储主要是MYSQL,但是数据分析主要是HADOOP+PGSQL。七、PG 的有多种集群架构可以选择,plproxy 可以支持语句级的镜像或分片,slony 可以进行字段级的同步设置,standby 可以构建WAL文件级或流式的读写分离集群,同步频率和集群策略调整方便,操作非常简单。八、一般关系型数据库的字符串有限定长度8k左右,无限长 TEXT 类型的功能受限,只能作为外部大数据访问。而 PG 的 TEXT 类型可以直接访问,SQL语法内置正则表达式,可以索引,还可以全文检索,或使用xml xpath。用PG的话,文档数据库都可以省了。九,对于WEB应用来说,复制的特性很重要,mysql到现在也是异步复制,pgsql可以做到同步,异步,半同步复制。还有mysql的同步是基于binlog复制,类似oracle golden gate,是基于stream的复制,做到同步很困难,这种方式更加适合异地复制,pgsql的复制基于wal,可以做到同步复制。同时,pgsql还提供stream复制。十,pgsql对于numa架构的支持比mysql强一些,比MYSQL对于读的性能更好一些,pgsql提交可以完全异步,而mysql的内存表不够实用(因为表锁的原因) 最后说一下我感觉 PG 不如 MySQL 的地方。第一,MySQL有一些实用的运维支持,如 slow-query.log ,这个pg肯定可以定制出来,但是如果可以配置使用就更好了。第二是mysql的innodb引擎,可以充分优化利用系统所有内存,超大内存下PG对内存使用的不那么充分,第三点,MySQL的复制可以用多级从库,但是在9.2之前,PGSQL不能用从库带从库。第四点,从测试结果上看,mysql 5.5的性能提升很大,单机性能强于pgsql,5.6应该会强更多.第五点,对于web应用来说,mysql 5.6 的内置MC API功能很好用,PGSQL差一些。 另外一些:pgsql和mysql都是背后有商业公司,而且都不是一个公司。大部分开发者,都是拿工资的。说mysql的执行速度比pgsql快很多是不对的,速度接近,而且很多时候取决于你的配置。对于存储过程,函数,视图之类的功能,现在两个数据库都可以支持了。另外多线程架构和多进程架构之间没有绝对的好坏,oracle在unix上是多进程架构,在windows上是多线程架构。很多pg应用也是24/7的应用,比如skype. 最近几个版本VACUUM基本不影响PGSQL 运行,8.0之后的PGSQL不需要cygwin就可以在windows上运行。至于说对于事务的支持,mysql和pgsql都没有问题。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Tsar是淘宝的一个用来收集服务器系统和应用信息的采集报告工具,如收集服务器的系统信息(cpu,mem等),以及应用数据(nginx、swift等),收集到的数据存储在服务器磁盘上,可以随时查询历史信息,也可以将数据发送到nagios报警。 Tsar能够比较方便地增加模块,只需要按照 tsar 的要求编写数据的采集函数和展现函数,就可以把自定义的模块加入到tsar中。 安装 Tsar目前托管在GitHub上,下载编译安装步骤: [azureuser@mono tsar-master]$sudo wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-check-certificate [azureuser@mono tsar-master]$ sudo unzip tsar.zip [azureuser@mono tsar-master]$ cd tsar [azureuser@mono tsar-master]$ sudo make [azureuser@mono tsar-master]# sudo make install 定时任务配置:/etc/cron.d/tsar,负责每分钟调用tsar执行采集任务;日志文件轮转配置:/etc/logrotate.d/tsar,每个月会把tsar的本地存储进行轮转;Tsar配置文件路径:/etc/tsar/tsar.conf,tsar的采集模块和输出的具体配置;模块路径:/usr/local/tsar/modules,各个模块的动态库so文件;Tsar配置 Tsar刚安装完,还没有历史数据,想要check是否正常,执行tsar -l,查看是否有实时信息输出: [azureuser@mono tsar-master]$ tsar -l Time ---cpu-- ---mem-- ---tcp-- -----traffic---- --sda--- --sdb--- ---load- Time util util retran pktin pktout util util load1 17/08/13-02:52:11 0.20 19.78 0.00 0.00 0.00 0.40 0.00 0.00 Tsar的配置主要都在/etc/tsar/tsar.conf中,常用的有: 增加一个模块,添加 mod_ on 到配置文件中打开或者关闭一个模块,修改mod_ on/offoutput_stdio_mod 能够配置执行tsar时的输出模块output_file_path 采集到的数据默认保存到的文件(如果修改的话需要对应修改轮转的配置/etc/logrotate.d/tsar)output_interface 指定tsar的数据输出目的,默认file保存本地,nagios/db输出到监控中心/数据库中,这两个功能还需要结合其它配置Tsar使用 查看历史数据,tsar-l/–list 查看可用的模块列表-l/–live 查看实时数据,tsar -l –cpu-i/–interval 指定间隔,历史,tsar -i 1 –cpu–modname 指定模块,tsar –cpu-s/–spec 指定字段,tsar –cpu -s sys,util-d/–date 指定日期,YYYYMMDD或者n代表n天前-C/–check 查看最后一次的采集数据-d/–detail 能够指定查看主要字段还是模块的所有字段-h/–help 帮助功能高级功能 输出到nagios配置: 首先配置output_interface file,nagios,增加nagios输出 然后配置nagios服务器和端口,以及发送的间隔时间 The IP address or the host running the NSCA daemon server_addr nagios.server.com The port on which the daemon is running - default is 5667 server_port 8086 The cycle of send alert to nagios cycle_time 300 由于是nagios的被动监控模式,需要制定nsca的位置和配置文件位置 nsca client program send_nsca_cmd /usr/bin/send_nsca send_nsca_conf /home/a/conf/amon/send_nsca.conf 接下来制定哪些模块和字段需要进行监控,一共四个阀值对应nagios中的不同报警级别 tsar mod alert config file threshold [hostname.]servicename.key;w-min;w-max;c-min;cmax; threshold cpu.util;50;60;70;80; 输出到mysql配置: 首先配置output_interface file,db,增加db输出 然后配置哪些模块数据需要输出 output_db_mod mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udpmod_io 然后配置sql语句发送的目的地址和端口 output_db_addr console2:56677 目的地址在该端口监听tcp数据,并且把数据入库即可,可以参照tsar2db:https://github.com/kongjian/tsar2db 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
DES是一种对称加密(Data Encryption Standard)算法,于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法。一般密码长度为8个字节,其中56位加密密钥,每个第8位都用作奇偶校验。 DES算法一般有两个关键点,第一个是加密模式,第二个是数据补位,加密模式的主要意义就是,加密算法是按块进行加密的,例如 DES ,是 64Bit 一个块的进行加密,就是每次加密 8 个字节,因此每次输入八个字节的明文输出八个字节密文,如果是 16 个字节,那么分成两个块依次进行加密,问题就出现在这里,如果明文是 1234567812345678,分块分别进行加密,那么加密的结果类似“C4132737962C519C C4132737962C519C”,可以看出明文的规律,这就是 ECB 加密模式,密文可以看出明文的规律;为了解决这个问题,有了其他的加密模式:CBC 加密模式(密码分组连接),CFB加密模式(密码反馈模式),OFB加密模式(输出反馈模式)CBC 是要求给一个初始化的向量,然后将每个输出与该向量作运算,并将运算的结果作为下一个加密块的初始化向量,CFB 和 OFB 则不需要提供初始化向量,直接将密码或者输出作为初始化向量进行运算;这样就避免了明文的规律出现在密文中;当然缺点是解密时需要保证密文的正确性,如果网络传输时发生了一部分错误,则后面的解密结果就可能是错误的;(ECB模式仅影响传输错误的那个块。密码算法基本上都是分组(按快)进行加密的,如果密文长度不是刚刚好可以进行分组,怎么办?只能进行填充。 加密算法常见的有ECB模式和CBC模式: 第一种电子密本方式(ECB) ECB模式:电子密本方式,就是将数据按照8个字节一段进行DES加密或解密得到一段8个字节的密文或者明文,最后一段不足8个字节,则补足8个字节(注意:这里就涉及到数据补位了)进行计算,之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。将明文分成n个64比特分组,如果明文长度不是64比特的倍数,则在明文末尾填充适当数目的规定符号。对明文组用给定的密钥分别进行加密,行密文C=(C0,C1,……,Cn-1)其中Ci=DES(K,xi),i=0,1,…..,n-1。 这是Java封装的DES算法的默认模式. 第二种密文分组链接方式(CBC) 密文分组链接方式,在CBC方式下,每个明文组xi在加密前与先一组密文按位模二加后,再送到DES加密,CBC方式克服了ECB方式报内组重的缺点,但由于明文组加密前与一组密文有关,因此前一组密文的错误会传播到下一组。 这是.NET封装的DES算法的默认模式,它比较麻烦,加密步骤如下: 1、首先将数据按照8个字节一组进行分组得到D1D2……Dn(若数据不是8的整数倍,就涉及到数据补位了) 2、第一组数据D1与向量I异或后的结果进行DES加密得到第一组密文C1(注意:这里有向量I的说法,ECB模式下没有使用向量I) 3、第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2 4、之后的数据以此类推,得到Cn 5、按顺序连为C1C2C3……Cn即为加密结果。 第三种密文反馈方式(CFB),可用于序列密码 明文X=(x0,x1,……,xn-1),其中xi由t个比特组成0 第四种输出反馈方式(OFB),可用于序列密码 与CFB唯一不同的是OFB是直接取DES输出的t个比特,而不是取密文的t个比特,其余都与CFB相同。但它取的是DES的输出,所以它克服了CFB的密文错误传播的缺点 数据补位一般有NoPadding和PKCS7Padding(Java中是PKCS5Padding)填充方式,PKCS7Padding和PKCS5Padding实际只是协议不一样,根据相关资料说明:PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。但是封装的DES算法默认都是8字节,所以可以认为他们一样。数据补位实际是在数据不满8字节的倍数,才补充到8字节的倍数的填充过程。 NoPadding填充方式:算法本身不填充,比如.NET的padding提供了有None,Zeros方式,分别为不填充和填充0的方式。 PKCS7Padding(PKCS5Padding)填充方式:为.NET和Java的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8.比如: 加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888. .NET中的DES加密 对于.NET,框架在System.Security.Cryptography命名空间下提供了DESCryptoServiceProvider作为System.Security.Cryptography.DES加密解密的包装接口,它提供了如下的4个方法: public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) public override void GenerateIV() public override void GenerateKey() 从.NET类库封装情况,加解密需要传入一个Key和IV向量。而且Key必须为8字节的数据,否则会直接抛异常出来,当使用ECB模式下,不管传入什么IV向量,加密结果都一样。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Windows Server 2008就要上市了,用虚拟机安装了两个版本的,一个Server Core的,也就是类Unix的命令行管理的版本,另一个是企业板。IIS 7值得期待,但是Server Core上的IIS居然不支持Asp.net,甚至没有.NET Framework 。微软推出Server Core不就是为了在加强服务器的安全性吗,难道微软不要.NET 作为服务器,这点就比不上同为.NET Framework的实现的Mono,最新的Mono1.2.6,完全支持Asp.net 2.0, 不也一样好好跑在Linux的命令行下吗,当然图形界面可以方便管理员的管理工作,IIS 7.0已经完全用XML文件配置,像apache一样完全胜任用命令行管理了,期待微软在Server Core上支持.NET Framework. IIS团队的blog上有一篇文章IIS7 on Server Core中有一段说明: Server Core installations on Windows Server 2008 comes with certain differences than regular Windows Server 2008 OS installations. In a nutshell, .Net framework is not available (hence no ASP.Net) and there is no windows shell so GUI administration tools are not available. As a note, availability and support of .Net framework on Server Core installation option is being discussed so there is no final answer on that as of this date yet. 微软还在讨论,这个还有什么可讨论的啊,微软给出点魄力出来吧。 Windows Server 2008 图形界面版本(以下称Windows Server 2008 )默认安装的版本及应用程序会用到的版本,才能知道是否要再额外加装 .NET Framework 。 1. Windows Server 2008 默认刚安装完成后:.NET Framework 2.0 with Service Pack 1 2. Windows Server 2008 添加安装 Application Server Role:.NET Framework 3.0 with Service Pack 1 3. .NET Framework 3.5 需要另外下载安装,或者通过Windows update 更新 4. Windows Server 2008 "Core" 版本:没有安装且无法安装 .NET Framework,强烈要求微软加入.NET Framework的支持。另外即将发布的Vista SP1里,.NET Framework 3.0 & 2.0的SP1补丁包会随之而来。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
.NET Mass Downloader 如果把Mass看成一个单词,则软件的名称可以翻译为“团块下载器",难道把文件分成一块一块的分别下载?但mass的真正含义还是“多路访问交换系统"(Multiple Access Switching System,简称MASS)的意思,它将单个下载过程分成多个连接,一个连接负责一小块下载任务,同时进行下载,即使在下载过程中,某个连接意外中断,也并不影响其它的下载任务,整个下载过程也不会受到影响,而且中断的连接马上会重新连接,并从断点开始续传,这显然要比单个连接要快得多. VS2008虽然可以通过设定符号文件的方式调试(.NET框架库源代码可用了( 韩现龙译)),源码文件只能在调试过程中必要的时候被下载,在调试进行的过程中因下载源码而导致意外暂停。通过.NET Mass Downloader完成.NET整体源码的下载,而且可以通过配置VS 2005,以非常类似的方法在VS 2005中使用这些源码。Mass用来表示整体下载.NET Framework源码调试真是合适不过了。 在老外的blog看到好几篇关于这个项目的介绍,和大家分享一下,具体的设置和使用参照下面的文章: 1、Download All the .NET Reference Source Code at Once with Net Mass Downloader 2、.NET Mass Downloader 1.1 Released 3、.NET Mass Downloader 1.2 Released 4 NetMassDownloader Download .Net Framework Source Code At Once Without Any Visual Studio Installed , Enables Offline Debug In VS 2008,VS2008 Express Edition,2005 And CodeGear Rad Studio. 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
用 Redirect 方法可将浏览器重定向到另一个 URL,而不是将内容发送给用户。 这里有一篇文章介绍使用Redirect《Using Response.Redirect Effectively》 ,文章详细的讨论了Response.Redirect ,给出了一段代码: public static class HttpResponseExtensions { public static void RedirectUser(this HttpResponse response, string url) { if (response.IsRequestBeingRedirected) return; response.Redirect(url, false); var context = HttpContext.Current; if (context != null) { context.ApplicationInstance.CompleteRequest(); } } }``` 另外ASP.NET 4 增加了一个RedirectPermanent方法,该方法同样是重定向,但生成的HTTP响应状态不是上边所演示的302,而是301(永久跳转),301 是对搜索引擎最友好的重定向方式。你有个网站http://www.cnblogs.com ,当人们访问http://www.cnblogs.com 这个URL时,你就把他们重定向到http://www.cnblogs.com/shanyou/,那么当搜索引擎爬到http:www.cnblogs.com这个网址时,如果它不能很好地跟随重定向,则它将认为http://www.cnblogs.com页面时没有内容的,所以这个页面的排名将会非常靠后。 如果我们把一个地址采用301 跳转方式跳转的话,搜索引擎会把老地址的PageRank等信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。
MSBuild 是 Microsoft 和 Visual Studio的生成系统。它不仅仅是一个构造工具,应该称之为拥有相当强大扩展能力的自动化平台。MSBuild平台的主要涉及到三部分:执行引擎、构造工程、任务。其中最核心的就是执行引擎,它包括定义构造工程的规范,解释构造工程,执行“构造动作”;构造工程是用来描述构造任务的,大多数情况下我们使用MSBuild就是遵循规范,编写一个构造工程;MSBuild引擎执行的每一个“构造动作”就是通过任务实现的,任务就是MSBuild的扩展机制,通过编写新的任务就能够不断扩充MSBuild的执行能力。所以这三部分分别代表了引擎、脚本和扩展能力。 构造工程(脚本文件) 先说说构造工程,只要通过Notepad打开任何一个Visual Studio下的C#工程(csproj)文件,就知道构造工程到底是怎么回事了。 <?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Root>$(MSBuildStartupDirectory)</Root> </PropertyGroup> <Target Name="Build"> <!-- Compile --> <ItemGroup> <ProjectToBuild Include="$(Root)\..\src\Foundation\Common\Gimela.Common.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Infrastructure\Gimela.Infrastructure.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Management\Gimela.Management.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Security\Gimela.Security.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Tasks\Gimela.Tasks.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Text\Gimela.Text.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Net\Gimela.Net.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\ServiceModel\Gimela.ServiceModel.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Data\Gimela.Data.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Presentation\Gimela.Presentation.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Media\Gimela.Media.sln" /> <ProjectToBuild Include="$(Root)\..\src\Foundation\Streaming\Gimela.Streaming.sln" /> <ProjectToBuild Include="$(Root)\..\src\Crust\Gimela.Crust.sln" /> </ItemGroup> <MSBuild Projects="@(ProjectToBuild)" Targets="Build" Properties="Configuration=Debug;"> <Output TaskParameter="TargetOutputs" ItemName="AssembliesBuiltByChildProjects" /> </MSBuild> </Target> </Project> 在构造工程中我们可以定义和使用变量(通过Property/PropertyGourp/Item/ItemGroup等元素),可以使用条件分支(通过Choose/When/Otherwise等元素)、能够在运行时给变量赋值(通过执行任务,获取其返回类型参数的方式)、能够定义执行块(通过Target元素,相当于函数)、能够进行异常处理(通过OnError元素)、还可以复用已有工程定义的内容(通过Import元素)。拥有这些能力和高级语言已经相差无几了,所以笔者认为构造工程不是描述性语言,而是脚本语言。 这里还需要强调一点的是,项目级元素(Property)可以在元素下定义,也可以在构造过程中作为外部参数传入,这是一个非常有用的特性,一般编译时选择配置项(Debug或者Release)就是利用这个特性实现的。 Project元素 这是每一个项目文件的最外层元素,它表示了一个项目的范围。如果缺少了这一元素,MSBuild会报错称Target元素无法识别或不被支持。 Project元素拥有多个属性,其中最常用到的是DefaultTargets属性。我们都知道,在一个项目的生成过程中可能需要完成几项不同的任务(比如编译、单元测试、check-in到源代码控制服务器中等),其中每一项任务都可以用Target来表示。对于拥有多个Target的项目,你可以通过设置Project的DefaultTargets(注意是复数)属性来指定需要运行哪(几)个Target,如果没有这个设置,MSBuild将只运行排在最前面的那个Target。 Property元素 在项目中你肯定需要经常访问一些信息,例如需要创建的路径名、最终生成的程序集名称等。以name/value的形式添加进Property,随后就可以以$(PropertyName)的形式访问。这样你就无须为了改动一个文件名称而让整个项目文件伤筋动骨了。比如上面代码中的Bin就是将要创建的路径名称,而AssemblyName则是最终要生成的程序集名称。这些属性的名称不是固定的,你完全可以按自己的习惯来进行命名。在使用时,你需要把属性名称放在”$(“和”)”对内(不包括引号),以表示这里将被替换成一个Property元素的值。 另外,如果Property元素数量比较多,你还可以把它们分门别类地放在不同的PropertyGroup里,以提高代码的可阅读性。这对Property本身没有任何影响。 <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>8.0.30703</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{6C2561FB-4405-408F-B41B-ACE5E519A26E}</ProjectGuid> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>Gimela.Infrastructure.Patterns</RootNamespace> <AssemblyName>Gimela.Infrastructure.Patterns</AssemblyName> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> </PropertyGroup> Item元素 在整个项目文件中你肯定要提供一些可被引用的输入性资源(inputs)信息,比如源代码文件、引用的程序集名称、需要嵌入的图标资源等。它们应该被放在Item里,以便随时引用。语法是: 其中Type属性可以被看作是资源的类别名称,比如对于.cs源文件,你可以把它们的Type都设置为Source,对于引用的程序集把Type都设置为Reference,这样在随后想引用这一类别的资源时只要引用这个Type就可以了,方法是@(TypeName)。可千万别和Property的引用方法弄混了。 既然Type是资源的类名,那么Include就是具体的资源名称了,比如在上面的示例代码中,Include引用的就是C#源代码文件的名称。你也可以用使用通配符*来扩大引用范围。比如下面这行代码就指定了当前目录下的所有C#文件都可以通过@(Source)来引用: <Item Type=”Source” Include=”*.cs” /> 另外,你也可以通过与PropertyGroup类似的方法把相关的Item放在ItemGroup里。 <ItemGroup> <Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="System.Data" /> <Reference Include="System.ServiceModel" /> <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> <Compile Include="Commands\CommandBase.cs" /> <Compile Include="Commands\DuplexCommandBase.cs" /> <Compile Include="Commands\ICommand.cs" /> <Compile Include="Commands\IDuplexCommand.cs" /> <Compile Include="Extensions\BitConverterExtensions.cs" /> <Compile Include="Extensions\ConcurrentDictionaryExtensions.cs" /> <Compile Include="Extensions\StopwatchExtensions.cs" /> <Compile Include="Extensions\TimeSpanExtensions.cs" /> <Compile Include="Flyweight\FlyweightObjectPool.cs" /> <Compile Include="Singleton\StaticSingleton.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="SmartQueue\ISmartQueueMapper.cs" /> <Compile Include="SmartQueue\SmartQueue.cs" /> <Compile Include="SmartQueue\SmartQueueBase.cs" /> <Compile Include="SmartQueue\SmartQueueMapper.cs" /> <Compile Include="UnitOfWork\IUnitOfWork.cs" /> <Compile Include="UnitOfWork\IUnitOfWorkFactory.cs" /> <Compile Include="UnitOfWork\UnitOfWork.cs" /> <Compile Include="WeakActions\IWeakActionExecuteWithObject.cs" /> <Compile Include="WeakActions\WeakAction.cs" /> <Compile Include="WeakActions\WeakActionGeneric.cs" /> <Compile Include="WeakFuncs\IWeakFuncExecuteWithObjectAndResult.cs" /> <Compile Include="WeakFuncs\WeakFunc.cs" /> <Compile Include="WeakFuncs\WeakFuncGeneric.cs" /> </ItemGroup> Target元素 Target表示一个需要完成的虚拟的任务单元。每个Project可以包括一个或多个Target,从而完成一系列定制的任务。你需要给每个Target设置一个Name属性(同一Project下的两个Target不能拥有同样的Name)以便引用和区别。 举例来说,在你的项目生成过程中可能需要完成三个阶段的任务:首先check-out源代码,接下来编译这些代码并执行单元测试,最后把它们check-in。那么通常情况下你可以创建三个不同的Target以清晰划分三个不同的阶段: <Target Name=”CheckOut” ></Target> <Target Name=”Build” DependsOnTargets=”CheckOut”> <Task Name=”Build” .../> <Task Name=”UnitTest” ... /> </Target> <Target Name=”CheckIn” DependsOnTargets=”CheckOut;Build”> </Target> 这样,你就可以非常清晰地控制整个生成过程。为了反应不同Target之间的依赖关系(只有Check-in后才能编译,只有编译完成才可能Check-out……),你需要设置Target的DependsOnTargets属性(注意是复数),以表示仅当这些Target执行完成之后才能执行当前的Target。当MSBuild引擎开始执行某项Target时(别忘了Project的DefaultTargets属性),会自动检测它所依赖的那些Target是否已经执行完成,从而避免因为某个生成环节缺失而导致整个生成过程发生意外。 你可以通过Project的DefaultTargets属性指定MSBuild引擎从哪(几)个Target开始执行,也可以在调用MSBuild.exe时使用t开关来手动指定将要运行的Target,方法如下: MSBuild /t:CheckOut 这样,只有CheckOut(以及它所依赖的Target,在上文中没有)会被执行。 Task元素 这可能是整个项目文件中最重要的,因为它才是真正可执行的部分(这也是为什么我在上面说Target是虚拟的)。你可以在Target下面放置多个Task来顺序地执行相应的任务。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
这两天看了一本书《Grails权威指南》,看了这个Java上Rails框架,其中有两条设计理念:1、make simple thing easy and make complex possible -让简单的事情变的容易,同时让复杂的事情的实现成为可能2、Convention Over Configuration --约定高于配置Rails几乎成了敏捷web框架的代名词,Java社区的Grails,.NET开源项目Mono Rails和Subsonic,还有微软ASP.NET Team正在做的ASP.NET MVC框架无不体现着上述两项设计理念。看看在.NET进行Rails式的敏捷开发工具包:1、MVC框架: 无论是Castle MonoRail还是ASP.NET 的MVC框架清晰,简洁,你要用这两个开发web框架,就一定要按他的方式做,model文件就放在models目录里,controller,view,helper分别放在特定名称的目录里,只要你按这个规则做了,那一切很简单,如果你较真抬杠非不这么放,那么也许能达到目标,但很累。不过在他的地盘上开发,为什么要不按人家的规则做呢,况且人家的目录结构,命名规则以及URL到action的映射都很合理很清晰,Mix上会发布的asp.net mvc 在URL Routing上会有很大的增强,MonoRail项目也在加强URL Routing这块的内容,看来自己要创建一套规则也容易。只是自己创建一套规则是否会更好。2、O/R Mapping: NHibernate,IbatisNet等ORM架构都有至少有一个记录OR映射关系的配置文件,然而Rails框架没有,它使用Scaffold生成model,默认情况下就是英文复数的表名对应单数的Model,DB字段名对应Model字段名,表中必须有叫做ID的整形字段作为key等等很直觉的约定。这样开发者就不用为了“可能”存在的灵活性而维护一个大的OR Mapping配置了。这样简单的事情容易了。SubSonic项目和Castle的ActiveRecord的子项目,由于.net静态语言的原因,在动态特性的实现上没有RoR中那么灵活,它基于.net中的attribute来标识字段和关系,SubSonic 不是在运行时执行基于反射的映射,而是直接生成和编译数据访问层。他们的设计模式都是ActiveRecord,ActiveRecord做CRUD很简单,每个对象可以有自己的Fetch,FetchByxxx方法,从开发者的角度看这些对象,它们知道如何加载和保存自己,对象自己来维护IsDirty之类的标识,开发者不必关心这个对象应该被insert还是update。3、Ajax,这年头,一个web框架肯定要支持ajax,asp.net mvc框架目前对ajax的支持方面很多人用jQuery做例子的很多。MonoRail之前默认用的是prototype库,MonoRail团队正在支持其他的javascript框架,可参看jQuery 和 MonoRail4、Loger: 对一个web应用,log是很常用的,Castle 框架和spring.net,MS企业类库都有log,还有一个更通用的Log库,可参看通用日志5、Mails: 对一个web应用,log是很常用的,Castle框架里面的支持很全面,从邮件模板到Mail发送的封装等6、作业调度:对一个Web应用,用作业调度去完成一些系统维护和生成报表功能,是不可缺少的,这也有一个通用的项目支持开源的作业调度框架 - Quartz.NET 7、IOC容器:微软也在搞IOC,名叫Unity ,园子里有兄弟介绍了,可参看依赖注入容器Unity Application Block(1):快速入门。只是这还是一个婴儿,还没法和Castle、Spring.NET等开发了好几年的框架相提并论。4、动态语言:随着DLR的到来,动态语言也来到了.NET,DLR现在发布Alpha 8, SliverLight 2.0的到来,DLR就将就充当一个重要角色,也就是IronPython、IronRuby这样的动态语言正式进入我们的工具箱。 这么多的工具包,就是没有一个完整包装的框架,最完整的框架算是Castle的MonoRail框架,借助Castle的4年来的积累,还在继续前行,微软要推出asp.net mvc而打断了MonoRail项目的开发步伐。SubSonic 本身是一个功能非常强大的应用程序工具集;如与 ASP.NET MVC 配合使用,它将成为非常有用的应用程序框架。总之,贯穿RoR的设计理念,这点对我们用.NET开发是很好的借鉴。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
要想成为Silverlight 的开发高手,熟练通达XAML语法是必由之路。现在我们来一个空的XAML模板。 Silverlight 1.0 的模板是这样的: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <!--声明各种Silverlight对象、资源和动画声明--> Silverlight 2.0的模板是这样的:xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <!--声明各种Silverlight对象、资源和动画声明--> 这两个XAML模板,最上层的Root Element分别以---和 --来声明,然后在其中开始声明格式各样的Silverlight对象。都有两样东西是一样的xmlns=http://schemas.microsoft.com/client/2007这是声明默认对应的命名空间,系统会将它当作默认值xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml以x:开头的XAML声明对应到这个个别的命名空间。你的XAML至少需要声明第一个命名空间,你的Silverlight才能够运行,否则就会产生错误,第二个命名空间在许多场合会用得到,所以把它也加入当作默认的模板。基础模板之下就需要加入布局容器了,当然在Silverlight 1.0里面你可以把TextBlock阿等等直接放在...之间,不过那样调整版面就很不方便。通常会加入一个花布。到了Silverlight 2.0在基础模板之后是必须加入布局容器的,然后才能添加Silverlight 控件,具体可参照Silverlight 教程第二部分:使用布局管理 (木野狐译)。Silverlight 2.0和Silverlight 1.0相比布局容器丰富多了,1.0只有一个Canvas,2.0拥有了WPF的三个容器了:Grid、Panel或Canvas.具体实例可参看Silverlight 教程第二部分:使用布局管理 (木野狐译)。不过这三个布局容器只能够选择一个,内部就可以任意嵌套了,非常的方便。本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Silverlight 运行时目前,Silverlight有两个运行时可以让用户体验到Silverlight内容 Silverlight 1.0 Silverlight 2.0 beta 1 两个运行时都支持丰富的媒体功能,并可以提供快速、低成本和高品质的音频和视频,支持主要浏览器 包括Firefox,Safari 和Internet Explorer ,支持windows和Mac操作系统。设计者(designer)在这两个运行时上的大体上是一样的,主要的区别是开发者(Developer)方面。Silverlight 2.0 beta1主要支持.net语言如Visual C#、Visual Basic。 下面表格中列出了Silverlight 1.0和Silverlight 2 Beta 1运行时功能比较 :Silverlight运行时特性表 功能 Silverlight 1.0 Silverlight 2 Beta 1 2D 矢量动画/图形 AJAX 支持 跨浏览器 (Firefox, IE, Safari) 跨平台 (Windows, Mac) 框架语言 (Visual Basic, Visual C#, IronRuby, Ironpython) - HTML DOM 集成 HTTP Networking 隔离存储(Isolated Storage) - JavaScript支持 JSON, REST, SOAP/WS-*, POX, 和RSS Web Services (以及对Sockets的支持) - 跨域网络访问 - LINQ to Objects - Canvas布局支持 StackPanel, Grid 和 Panel布局支持 - 托管的控件框架 - 整套控件(TextBox, RadioButton, Slider, Calendar, DatePicker, DataGrid, ListBox等等) - Deep Zoom 技术 - 托管的HTML桥 - 托管的异常处理 - 媒体 – 内容保护 - 媒体 – 720P 高清晰 (HD) 视频 媒体 – 音频/视频支持 (VC-1, WMV, WMA, MP3) 媒体 – 图像支持 (JPG, PNG) 媒体记号 丰富的核心框架(例如泛型,集合等) - 安全执行 - Silverlight ASP.NET 控件 (asp:media, asp:xaml) 类型安全确认 - Windows Meda Server支持 XAML Parser (基于WPF) XMLReader/Writer - Silverlight工具 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
原文:Developing a Custom Control for Silverlight 2.0 译者:张善友 Download MediaButton_demo - 131.06 KB Download MediaButton_src - 10.91 KB 介绍 这篇文章主要展示了你制作一个Silverlight 2.0的自定义空间需要哪些步骤和在你的Silverlight项目中重用代码。 本文基于Mix08上发布的Silverlight 2.0 beta1。 文章中我会创建一个控件库和实现自定义控件按钮类,没有任何新增功能只是继承缺省Button类,但是带一个不同原来的button的缺省样式。重用这个控件你不需要为你的项目中的所有控件实例添加Style属性。 让我们开始吧 创建项目 使用Visual Studio 2008新建一个Silerlight 类库项目。 因为这是一个控件库,我们要添加程序集System.Windows.Controls的引用,这个程序集在Silverlight 2.0 beta 1的版本号是1.0.0.0(不要问为什么:-) ),默认会并放在"C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client\System.Windows.Controls.dll"。 下一步是给我们的控件程序集加入XmlnsDefinitionAttribute。 这个特性帮助XAML处理器找到和匹配Xml命名空间和CLR的命名空间,因此添加这个特性带下面的参数: [assembly: System.Windows.Markup.XmlnsDefinition ("http://schemas.eyedea.hu/silverlight/2008/xaml/presentation", "Eyedea.Controls")] 创建控件类 解决方案内找到Class1.cs文件,利用Visual Studio的重构功能,将Class1.cs重命名为MediaButton.cs。 下一步我们添加我们XAML文件,里面包含这个控件库里面的控件要使用的缺省样式。 让我们添加一个文本类型的项目到公秤里,命名为generic.xaml。 选择generic.xaml文件并设置为嵌入式资源。通过删除Custom Tool属性值并设置Build Action为Resource。 现在轮到编辑我们的主要对象:MediaButton.cs文件。打开这个文件,添加命令空间System.Windows.Controls的引用修改MediaButton类从系统内建的Button类继承。 我们的MediaButton类看起来像这个样子: using System.Windows.Controls;namespace Eyedea.Controls{ public class MediaButton : Button { public MediaButton() { } }} 给我们的控件加入默认的样式 打开文件general.xmal 首先添加下面的缺省内容到XAML文件和一个引用到我们的XML命名空间: <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:Eyedea.Controls;assembly=Eyedea.Controls"></ResourceDictionary> 请注意local这个Xml命名空间前缀将被用于这个控件库里面控件的样式引用。 添加Style标签到我们定义样式的地方,在Style标签有个TargeType属性指定该样式将使用在哪类控件,在这里指向我们的MediaButton,你还必须和TargeType属性一样指定ControlTemplate属性 <Style TargetType="local:MediaButton"> <Setter property="Template"> <Setter.Value> <ControlTemplate TargetType="local:MediaButton"> <Grid x:Name="RootElement"> </Grid> </ControlTemplate> </Setter.Value> </Setter></Style> 在Style标签内可以定义充分的控件外观包括StoryBoards式的视觉状态转换,视觉元素和StoryBoards的名称非常重要,因为他们是Silverlight的样式可以工作的不可或缺的一部分,这里我们不讨论,将在另外的文章中讨论。 当前控件设计有一个固定的宽度和高度,因此我们可以通过用Setter来指定。 我们也指定控件的最小和最大尺寸以保护我们设计的按钮。 提示:简单的属性Setters应直接放在Style标签之后和在Template标签之前。 <!-- Common properties --><Setter property="IsEnabled" Value="true" /><Setter property="IsTabStop" Value="true" /><Setter property="Margin" Value="0" /><Setter property="HorizontalContentAlignment" Value="Center" /><Setter property="VerticalContentAlignment" Value="Center" /><Setter property="Cursor" Value="Arrow" /><Setter property="Foreground" Value="#CC808080" /><!-- Text related properties --><Setter property="TextAlignment" Value="Left" /><Setter property="TextWrapping" Value="NoWrap" /><Setter property="FontSize" Value="11" /><!-- Default Size Constraints --><Setter property="Width" Value="50" /><Setter property="MinWidth" Value="50" /><Setter property="MaxWidth" Value="50" /><Setter property="Height" Value="22" /><Setter property="MinHeight" Value="22" /><Setter property="MaxHeight" Value="22" /> 添加视觉元到模板可复制我们的第一次Expression Design设计的以下xaml内容的一种样式。 这个设计包含一个背景矩形,一个大纲,两个亮点将在和用户交互的时候动画显示。 在底部你发现有一个ContentPresenter元素,它是Button的Content属性的占位符。 添加下列内容到Grid标签: <Grid.Resources> <Storyboard x:Key="MouseOver State"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightTop" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.3"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightBottom" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Border" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.7"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Key="Pressed State"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightTop" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightBottom" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.3"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="Border" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.5"/> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Key="Normal State" /> <Storyboard x:Key="Disabled State"> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightTop" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.1500000" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="HighlightBottom" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.1500000" Value="0"/> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ContentPresenter" Storyboard.Targetproperty="(UIElement.Opacity)"> <SplineDoubleKeyFrame KeyTime="00:00:00.1500000" Value="0.7"/> </DoubleAnimationUsingKeyFrames> </Storyboard></Grid.Resources><Rectangle Fill="#FF000000" Margin="2,2,2,2" RadiusX="1" RadiusY="1" Opacity="0.3"/><Rectangle x:Name="Border" Stroke="#FF808080" RadiusX="2" RadiusY="2" Opacity="0.3"/><Path x:Name="HighlightTop" Margin="2,2,2,11" Opacity="0.2" Data="M0,1 C0,0.45 0.45,0 1,0 L45,0 C45.55,0 46,0.45 46,1 C46,1 46,9 46,9 C46,9 0,9 0,9 C0,9 0,1 0,1 z"> <Path.Fill> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFFFFFFF" Offset="0"/> <GradientStop Color="#FFE1E1E1" Offset="1"/> </LinearGradientBrush> </Path.Fill></Path><Path x:Name="HighlightBottom" Margin="2,11,2,2" Opacity="0" Data="M0,0 C0,0 31,0 46,0 C46,0 46,8 46,8 C46,8.55 45.55,9 45,9 L1,9 C0.45,9 0,8.55 0,8 C0,8 0,0 0,0 z"> <Path.Fill> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFD6D6D6" Offset="0"/> <GradientStop Color="#FFFFFFFF" Offset="1"/> </LinearGradientBrush> </Path.Fill></Path><ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" FontStretch="{TemplateBinding FontStretch}" FontStyle="{TemplateBinding FontStyle}" FontWeight="{TemplateBinding FontWeight}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" TextAlignment="{TemplateBinding TextAlignment}" TextDecorations="{TemplateBinding TextDecorations}" TextWrapping="{TemplateBinding TextWrapping}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> 编译工程,如果一切正常,一个自定义控件就完成了 测试控件 要测试空间,我们需要创建一个Silverlight 应用工程。在解决方案浏览器中右击Solution节点选择添加一个Silverlight应用类型项目: 对于Silverlight应用,Visual Studio会问我们用那种方法测试Silverlight应用。为目前为止,我们选择一个HTML页面来测试比较合适。 设置TestApplication项目作为我们的启动项目,右击该项目的节点,并选择"设置为启动项目" 。 将我们控件加入测试项目 在测试项目TestApplication中测试我们的自定义控件,我们需要添加控件工程的引用。 在设计器打开Page.xaml文件并切换到XAML视图,为了在页面上使用MediaButton 控件,我们要在页面的XAMLUserControl标签中注册控件命名空间。 测试页面包含一个4乘3的网格Grid和两个MediaButton实例,内容为“Play”和“Stop”: 完成的Page.xaml内容如下: <UserControl x:Class="TestApplication.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:eyedea="clr-namespace:Eyedea.Controls;assembly=Eyedea.Controls" Width="320" Height="240"> <Grid x:Name="LayoutRoot" Background="Black" Margin="50,50,50,50"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.RenderTransform> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="2" ScaleY="2" /> </Grid.RenderTransform> <Rectangle Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" Stroke="#FF808080" RadiusX="2" RadiusY="2" Opacity="0.3"/> <eyedea:MediaButton Grid.Column="1" Grid.Row="1" Margin="2,2,2,2" Content="Play"> </eyedea:MediaButton> <eyedea:MediaButton Grid.Column="2" Grid.Row="1" Margin="2,2,2,2" Content="Stop"> </eyedea:MediaButton> </Grid></UserControl> 按F5测试控件,Silverlight2.0的键盘支持比Silverlight1.0要好得多。 下一步做什么 我计划写一篇文章,我将在这篇文章知识的基础之上建立一个可更换皮肤的控件。 和很多更多silverlight 2.0特性 ;-) 兴趣点 Our first How-Do-I video: The design of the MediaButton control (English). Our first How-Do-I video: The design of the MediaButton control (Hungarian). 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
Opserver是闻名遐迩的网站Stack Overflow的开源监控解决方案,由Stack Exchange发布。它基于.NET框架构建,这在监控工具领域有些与众不同。 旨在为每个受监控系统的健康状况提供一个快速的总体视图,还允许用户使用下钻方法进行深入挖掘。Nick Craver是Opserver的创建者之一,他告诉InfoQ: 我们认为,监控系统应该在一个较高的层次上展示系统,出现了什么错误,并允许用户通过下钻来了解更多细节。 Opserver以Web仪表板的形式进行组织,每个仪表板专门针对一个特定的系统。Opserver目前支持SQL Server、ElasticSearch、HAProxy、StackExchange.Exceptional和Redis。Orion是一款来自SolarWinds的商业工具。Opserver还使用它提供基础设施和网络监控。一次Opserver安装并不需要使用所有这些系统,因为它们可以基于选择进行配置。 以SQL Server为例,Opserver提供了关于CPU和内存消耗的高层次信息或者数据库的总体健康状况: 在概览视图下面,Opserver提供了额外的数据。例如,它提供了一个最常用查询的列表,可以按照多个条件进行排序(总执行时长、平均CPU消耗)。对于每个查询,它提供了更多的细节信息,包括查询执行计划(查询执行步骤的详细分解)。 SecuritySettings.config文件定义诸如身份验证方法这样的设置项: <?xml version="1.0" encoding="utf-8"?> <SecuritySettings provider="AD"> <!—可选,这些网络无须身份验证就可以看到概览仪表板--> <InternalNetworks> <Network name="SE Internal" cidr="10.0.0.0/8" /> </InternalNetworks> </SecuritySettings> <!-- 面向所有人的全局访问示例 <SecuritySettings provider="alladmin" /> --> 每个系统有一个配置文件。目前支持JSON格式。下面是SQL Server配置的一个例子: { "defaultConnectionString": "Data Source=$ServerName$; Initial Catalog=master;Integrated Security=SSPI;", "clusters": [ // 集群只能用于SQL Server 2012 { "name": "NY-SQLCL04", "refreshIntervalSeconds": 20, "nodes": [ { "name": "NY-SQL03" } ] } ], "instances": [ { //该实例不能使用defaultConnectionString,因此它得自己指定。 "name": "NY-DB05", "connectionString": "Data Source=NY-DB05; Initial Catalog=bob;Integrated Security=SSPI;", }, // defaultConnectionString中的服务器名会被“name” 替换 { "name": "NY-DESQL01" } ] } 如果Opserver没有包含某个特定场景,那么它还提供了若干扩展点,用户可以通过它们使用额外的仪表板和配置选项来增强该工具。按照计划,这个过程将来会更简单易用而且功能更强大: 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
XAML标签元素在silverlight运行时被转换成相应的对象,通过XamlReader类的Load方法,动态创建UI元素: 指定一条XAML内容字符串,为按照XML规则运行,XamlReader.Load()现在需要你在你的XAML文件中指定一个xmlns;通过XamlReader.Load方法把元素在内存中编译(这样就可以得到UI元素对象的引用,也有可能是null,或者报错);最后把它添加到容器的子控件中。下面我们来制作一个简单的时钟,Page.xaml如下: <UserControl x:Class="OpenXmlVideo2.Page" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="187" Height="97"> <Canvas x:Name="EClock" Height="97" Width="187" > </Canvas> </UserControl> Page.xaml.cs如下: using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Markup; namespace OpenXmlVideo2 { public partial class Page : UserControl { private TextBlock textBlock1; private System.Windows.Threading.DispatcherTimer timer; public Page() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Page_Loaded); } void Page_Loaded(object sender, RoutedEventArgs e) { string xaml = string.Empty; xaml = "<TextBlock xmlns=\"http://schemas.microsoft.com/client/2007\" Margin=\"14,11,19,12\" Name=\"textBlock1\" FontFamily=\"Time New Roman\" FontSize=\"40\">00:00:00</TextBlock>"; textBlock1 = XamlReader.Load(xaml) as TextBlock; //Loaded就是TextBlock的加载事件,那么里面的textBlock1_Loaded自然就是事件处理程序的名称。 textBlock1.Loaded += new RoutedEventHandler(textBlock1_Loaded); //改变附加属性(attached properties),必须使用SetValue方法 textBlock1.SetValue(Canvas.LeftProperty, 2); textBlock1.SetValue(Canvas.TopProperty, 2); //加把textBlock1对象做为子对象添加到画布(和asp.net页的控件树的道理相拟) this.EClock.Children.Add(textBlock1); } void textBlock1_Loaded(object sender, RoutedEventArgs e) { //使用了DispatcherTimer,我把间隔设置为1秒。该计时器的间隔事件也是Tick事件 timer = new System.Windows.Threading.DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 1); //间隔1秒 timer.Tick += new EventHandler(timer_Tick); timer.Start(); } void timer_Tick(object sender, EventArgs e) { textBlock1.Text = DateTime.Now.ToLongTimeString(); } } } 运行的结果如下: 一个简单的电子钟做好了。主要是学习两项内容:通过XamlReader类的Load方法,动态创建UI元素和DispatcherTimer。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
WCF Web API支持多个宿主环境:自宿主(windows服务或者控制台)和IIS宿主(asp.net webform/mvc)。这个入门文章主要演示在ASP.NET MVC3网站宿主: 如何使用NuGet向项目中添加Web Api引用如何创建一个通过HTTP GET访问的Web Api如何通过asp.net routes宿主一个Web Api如何通过浏览器或者Fiddler访问Web Api如何在Api上启用OData uri查询如何用WCF Web Test Client测试WCF Web API1、创建一个基本的解决方案:使用VS2010新建一个空的ASP.NET MVC 3 Web Application 设置站点的端口号为9000 2、向解决方案中加入Web Api的引用 通过NuGet来添加Web api的程序集引用,右击项目属性,选择“Manage NuGet Packages” 在NuGet管理扩展器上查询Online的”webapi.all“ 选择安装,NuGet就会下载所有所需的软件包,现在可以开始开发Web Api。 3、创建一个Contacts Api类 右击项目ContactManager选择添加一个文件夹,取名”APIs“,然后在APIs文件夹上右击添加类,类名叫做ContactsApi: using System.ServiceModel;namespace ContactManager.APIs{ [ServiceContract] public class ContactsApi { } }ContractsApi 加了ServiceContractAttribute表示这是一个WCF 服务,将通过HTTP方式暴露出来。4、通过asp.net routing注册ContractsApiApi需要通过asp.net mvc宿主,使用ASP.net Route的MapServiceRoute扩展方法把它注册进去。切换到global.asax.cs文件,添加以下引用using ContactManager.APIs;using System.ServiceModel.Activation;在RegisterRoutes方法里加入下述代码routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory(), typeof(ContactsApi))); 下面的黄色部分很重要,MVC的默认路由是映射到controller + action public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory(), typeof(ContactsApi))); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); }MapServiceRoute需要一个泛型参数指定服务(API),以及一个将被追加到IIS base url的路径。在这里,我们指定的“contacts”,也就是宿主为“http://localhost:9000/api/contacts”。 通过一个HTTP Get 方法暴露contacts:首先创建一个poco(Plain Old C#)Contract类,代表我们在api上传递的联系人,本质上就是一个DTO(数据传输对象),在HTTP上我们把它作为资源,然后创建一个HTTP Get方法暴露资源。 右击项目ContactManager项目选择添加新的文件夹“Resources”,在Resources文件下创建一个新的类Contact。 namespace ContactManager.Resources{ public class Contact { public int ContactId { get; set; } public string Name { get; set; } } }返回到ContactApi类,添加下述引用: using System.ServiceModel.Web;using ContactManager.Resources; 添加一个Get方法返回所有的contracts [WebGet(UriTemplate = "")]public IQueryable Get(){ var contacts = new List<Contact>() { new Contact {ContactId = 1, Name = "Phil Haack"}, new Contact {ContactId = 2, Name = "HongMei Ge"}, new Contact {ContactId = 3, Name = "Glenn Block"}, new Contact {ContactId = 4, Name = "Howard Dierking"}, new Contact {ContactId = 5, Name = "Jeff Handley"}, new Contact {ContactId = 6, Name = "Yavor Georgiev"} }; return contacts.AsQueryable(); } Get方法上加了WebGet Attribute表示这是一个HTTP Get。注意这里的UriTemplate被设置为“”,默认情况下,操作的Uri是方法名Get,在这种情况下,我们是在Route中设置的Uri。 6、通过浏览器查询Contracts.按F5运行项目,然后再浏览器地址栏中输入http://localhost:9000/api/contacts 7、查询返回Json格式的Contracts。HTTP提供了一些“内容协商”机制 — 当有多个可得的表现形式的时候,对特定的响应选择最好的表现形式的处理过程。 服务器驱动协商(Server-driven Negotiation) 如果响应的最好的表现形式的选择是通过服务器上的算法来实现,那么这种方式的协商称做服务器驱动协商。选择是基于响应可得的表现形式(根据不同的维度,响应会不同;例如,语言,内容编码,等等)和请求消息里特定的头域或关于请求的其他信息(如:网络客户端的地址)。 服务器驱动协商是有优点的,当从可行的表现形式里进行选择的算法对用户代理进行描述是比较困难的时候,或者当服务器期望发送“最好的猜测”给客户端而只通过一个响应(以避免后续请求的回路(一个请求会返回一个响应)延迟如果此“最好的猜测“对用户适合的时候)的时候。为了改善服务器的猜测,用户代理应该包含请求头域(Accept,Accept-Language,Accept-Encoding,等等),这些头域能描述它对响应的喜好。 Web api返回的响应很容易添加一种媒体类型(media types )。 打开Fiddler,在“Request builder”栏输入地址“http://localhost:9000/api/contacts”,然后移动到“Request Headers”在“User-Agent” 项下方添加 “Accept: application/json” wcfjson 按下 Exectue按钮,双击左边的Panel查看HTTP的response,切换到“Raw”Tab,你可以看到下面的json格式的数据: 8、启用OData 查询支持 Web API支持OData协议,接受OData的URI格式查询,当OData 查询到达Web Api, 在返回客户端之前在服务端会进行必要的过滤和排序。查询使用IQueryable 接口,服务端并没有去查询所有的数据,发送过滤和排序到服务端。 return contacts.AsQueryable(); 运行程序,在浏览器里输入 http://localhost:9000/api/contacts?$Top=4&$OrderBy=Name ,看到浏览器之返回了按名字排序的top 4个contract webapiodata也可以通过Fidder去查询,具体可参照第7步。 9、WCF Web API也提供了一个WCF Web Test Client用于测试WCF Web API,通过配置启用,在RegisterRoutes方法里创建HttpConfiguration 实例,并设置EnableTestClient属性为True: var config = new HttpConfiguration() { EnableTestClient = true }; 然后把HttpConfiguration实例传递给HttpServiceHostFactory的配置属性 routes.Add(new ServiceRoute("api/contacts", new HttpServiceHostFactory() { Configuration = config }, typeof(ContactsApi))); 按下F5 启动调试项目,然后再浏览器后面加入/Test 总结 通过这个Quick start,我们学习到了以下内容 如何使用NuGet向项目中添加Web Api引用 如何创建一个通过HTTP GET访问的Web Api 如何通过asp.net routes宿主一个Web Api 如何通过浏览器或者Fiddler访问Web Api 如何在Api上启用OData uri查询 如何用WCF Web Test Client测试WCF Web API 你可以在这里获取到代码。 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
今晚看到Mono老大的blog上有一个Mono on the iPhone, 就是最近Sun公司还在为iPhone上运行Java 苹果没兴趣 Sun单干。 .NET已经借助Mono捷足先登了。 PADL Software 公司的Luke Howard 发给Miguel de Icaza's的一些Mono 在iPhone上运行的截图: Some stats: # 本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号
加数位 被加数位 进位 这三个位 ,
有一个1,结果为1,无进位
有两个1,结果为0,有进位
有三个1,结果为1,有进位
从左向右运算
减法运算其实是可以由加法运算替代的,我们上面已经介绍过了无符号和补码的非,其实很多CPU是没有减法运算器的,它们都是将减数进行逆运算以后送入加法器,然后进行加法运算,这样得出来的结果就是减法运算最终的结果。
比如我们考虑一种简单的情况,当w = 4时的无符号减法运算,对于 5 - 4这个减法运算来说,我们可以由 5 + 4-1(其中4-1是4的逆元的意思,不是1/4的意思)来替代这个减法运算。
为了更加直观,LZ带各位来算一下,首先4的逆元根据上面的公式可以得到为 4-1 = 24 - 4 = 12 。那么我们现在需要对5和12进行加法运算,它们的位表示分别为 0101和1100,结果为10001,也就是十进制17的位表示。不过由于我们的w = 4,因此截断之后结果为0001,也就是十进制的1。最终可以得到 5 - 4 = 1。
对于5 - 4来说,是考虑的结果为正的情况。或许有的猿友会对结果为负或者说是无符号数溢出的情况下有疑问,因此LZ这里对这种情况也做一个简单的介绍。我们考虑一个简单的计算 0 - 1,我们可以得到1-1 = 24 - 1 = 15。此时对0和15进行加法运算,他们的位表示分别为0000和1111,结果为1111。
看到这里估计有的猿友会奇怪了,这怎么回事,0 - 1 = 15。
当然不是,这个结果其实是正确的。考虑使用补码编码来解析1111这个位表示,它代表的值就是-1。15是1111这个位表示在无符号编码情况下的解析结果。
因此LZ这里也给出一个公式,就是对于两个整数x和y来说,x - y = x + y-1。这里需要特别说明的是,这个公式代表的意义是位表示,而不是实际的数值。
-------------------------
应该是字节
-------------------------
字节