目前在AppHarbor中使用Entity Framework Code First的默认设置会出现一些问题,因为EF默认会执行DropCreateDb,而AppHarbor咩有给我们Drop的权限。

目前AppHarbor提供的解决办法是使用这个Nuget package

然而使用这个package也有个个问题就是这个package里虽然没有明说,但实际上不支持目前最新的EF 4.3.1,因为最新的EF提供的Migrations功能已经和以前不同,已经不会有什么EdmMetadata之类的表。总之解决方案就是老老实实的使用EF 4.1.*

而且这个package还小题大做的用到了WebActivator,个人感觉只要在Application_Start里加代码就好了吧- -

虽然各种不爽总之是能跑起来了-v-

顺便要吐槽的是AppHarbor的文档真是orz啊,比如说了写什么connection string alias在EF code first中用不了啊神马的,实际上是可以的,但是想要加上"MultipleActiveResultSets=True;"的话大概还是要写一些代码的,参考文档吧,我还没试。

posted @ 2012-05-13 18:40 jiaxingseng 阅读(30) 评论(0) 编辑

1首先是在本机安装git环境,这个大家写过的比较多了,简略一点。

1.1 下载安装msysgit

      地址http://code.google.com/p/msysgit/downloads/list

      下载最新的“Full installer for official Git for Windows”

      最新的msysgit安装过程简略了很多,没有过去那么多选项。全都下一步就ok。

1.2 下载安装tortoisegit,windows下有这个还是比较简单

      地址http://code.google.com/p/tortoisegit/downloads/list

      最新版据说已经解决了文件名编码的问题。

1.3 VS中安装扩展Git Source Control Provider

      这一步不做也成。

2 用github托管源代码

2.1 首先照着这里做

      http://help.github.com/win-set-up-git/

      前面那些安装过程我们都做过了,从Set Up SSH Keys这一节开始就好。

2.2 确认账户信息配置完毕后,创建自己的代码库。

      https://github.com/new

      代码库类型选择默认的public就好,反正版权不值钱-v-

      那个Initialize this repository with a README就选上吧,省得自己做一次初始化了。

      image

2.3 在本地某个文件夹clone吧

      右键->Git Clone...

      Url填入你的代码库的http地址吧,SSH的貌似不行。。。总之大体是这样

      image

      image

2.4 在本地工作目录下尝试新建一个ASP.Net MVC3工程,commit之后push

      应该能在github里看到自己提交的代码了。

      image

3 在AppHarbor创建自己的application

   去创建就好了,傻瓜式的,暂时不需要各种高级功能,基本上填个名字就ok。。。

   https://appharbor.com/

4 连接github与AppHarbor

4.1 这里有教程,照做就是

      http://blog.appharbor.com/2011/10/13/announcing-github-support

      由于刚才选的是public的代码库,所以有关private的内容统统不用理会,真是简单明快呢-v-

      顺便说一下,github那边所说的“Create build URL”,实际指的是AppHarbor那边的那个“BUILD URL”那个按钮。那个按钮点击之后会把build的url copy进剪贴板,找个地方粘贴一下就能看到了。那个按钮本身是flash做的,浏览器block的童鞋们注意一下。

      image

4.2 确认效果

      如果成功的话,之后的每次向github push应该都会触发一次AppHarbor的build。暂时没有想提交的东西也没关系,可以在刚才github那边点一下那个“Test Hook”。

      image

      总之如果成功连接,回到AppHarbor的application后台主页那里,就应该能看到最近的build情况了

      image

      Build没有问题的话,点击“Go to your application”,熟悉的Mvc界面就出现啦~\(≧▽≦)/~

      image

posted @ 2012-05-11 21:44 jiaxingseng 阅读(805) 评论(4) 编辑

我有这么个需求:

项目里想使用Common.Logging来输出log,但并不想固定的依赖log4net或者NLog之类的,所以我不能直接install log4net之类的package。但是运行时当然又需要,所以我要写个build脚本,整体build完了之后把log4net.dll之类的copy到debug下面。

于是问题就来了:我的所有project都没有依赖log4net,所以packages目录下自然就没有log4net.1.2.10咯,那我copy的时候source是啥?

首先想到的自然是Nuget从1.6开始提供的package restore功能,反正我已经自己写脚本了,调用一下NuGet.targets不就好了?

事实证明我图样图森破了。。。 打开NuGet.targets

 

<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>

 

为毛写死了不许自定义啊。。。没关系,咱改了它

<PackagesConfig  Condition="$(PackagesConfig) == ''">$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>

之后在我的脚本里添加如下内容

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Buid" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>    
    <RestorePackages>true</RestorePackages>
    <PackagesConfig>$([System.IO.Path]::Combine($(MSBuildProjectDirectory), "MyComany.MyProduct.MySolution.Packages.config"))</PackagesConfig>
  </PropertyGroup>

  <Import Project="..\.nuget\nuget.targets" />

  <!--Build All-->
  <Target Name="Buid">
    <CallTarget Targets="RestorePackages"/>
  </Target>
</Project>

结果一运行,报错说我的"MyComany.MyProduct.MySolution.Packages.config"找不到。

我检查了好几遍路径都没错啊~~~结果把文件重命名为packages.config,成功了。。。

最后看了一下帮助(nuget help install)

usage: NuGet install packageId|pathToPackagesConfig [options]

Installs a package using the specified sources. If no sources are specified, all
 sources defined in %AppData%\NuGet\NuGet.config are used.  If NuGet.config spec
ifies no sources, uses the default NuGet feed.

     Specify the id and optionally the version of the package to install. If a
     path to a packages.config file is used instead of an id, all the packages
     it contains are installed.

你妹啊!为啥只认packages.config啊!


posted @ 2012-05-04 15:21 jiaxingseng 阅读(81) 评论(0) 编辑

Task的API设计确实有很多令人迷惑的地方,所以真的非常感谢Stephen Toub的这篇FAQ。节译其中的主要部分。

1.Q:我应该什么时候使用Task.Start?

   A:Start实例方法可以用在且只能用在task处在Created状态(也就是task.Status返回TaskStatus.Created),而唯一能使task处在这一状态的方式就是使用Task的public构造器

2.Q:我有一个由Task.Run / Task.ContinueWith / Task.Factory.StartNew / TaskCompletionSource / 异步方法创建的task,我能不能对其调用Start方法?

   A:如上所述,不能。会抛异常的。以上任意一个方法创建的task都意味着task不再处在Created状态,而是其他状态例如TaskStatus.WaitingForActivation、TaskStatus.Running、TaskStatus.RanToCompletion

3.Q:Start方法实际上做了什么?

   A:它把task放入目标TaskScheduler(无参的Start方法意味着目标TaskScheduler为TaskScheduler.Current)。当你使用构造器创建一个task,它处于非活动状态,也就是说没有被放入任何一个TaskScheduler,因而没人会运行它。如果你不调用Start方法,它永远不会被放入队列,所以永远不会完成。想让task被执行,就需要把它放入队列,这样调度器会在它认为合适的时机运行你的task。Start方法会对task对象做一些变化(例如修改状态为WaitingToRun),之后调用目标TaskScheduler的QueueTask方法将其放入队列,从此时开始,task未来的运行就交由调度器处理,调度器最终会调用TryExecuteTask方法执行你的task。

4.Q:我能对同一个task多次调用Start方法么?

   A:不能。一个task从Created状态变到别的状态这个行为只能出现一次,Start方法就会导致这个行为,所以Start方法也只能被调用一次。多次调用只会导致异常。Start方法引入了同步机制来保证task对象处在一致性的状态,所以即使多次并发的调用Start方法,也只有其中的一次调用会成功。

5.Q:Task.Start和Task.Factory.StartNew有什么不同?

   A:Task.Factory.StartNew是一种简略的写法,实际就是构造一个task然后Start,所以如下的代码

var t = Task.Factory.StartNew(someDelegate);

和如下的代码从效果上是相同的

var t = new Task(someDelegate);
t.Start();

但从性能上来说,前者更好。如#3中所说,Start方法引入了同步机制来保证该task在Start之前尚未Start,也不会被并发的多次Start。与之相对的,StartNew方法知道不可能有其他人Start这个task因为这个引用尚未返回给任何人,所以StartNew方法无需引入同步机制。

6.Q:我听说调用Task.Result也可以开始一个task?

   A:没这回事。当一个task处在Created状态,只有两种可能性使其变化到其他状态。

1. 构造task时传入了一个CancellationToken,当task还在Created状态时有了取消请求,那么task会变化为Canceled状态。

2. 有人调用了Start方法

调用Result不属于上述两种之一。当你对一个还处在Created状态的task调用Wait方法或者Result,调用会被阻塞。直至有人调用了Start,之后balabala,最终task完成了,被阻塞的调用才会完成。

你以为调用Result可能会开始一个task,那是不对的。实际上那倒有可能导致task被“内联”的执行。当task已经被放入TaskScheduler的队列,它也许并未开始,依然躺在队列里,当你对这种task调用Result,运行时可能会尝试内联的执行这个task(也就是说在你的调用线程上执行task),而不会等某个其他线程啥时候闲下来有空。从内部来说,就是Result内部也许会调用TaskScheduler的TryExecuteTaskInline方法,当然以上所说的“也许”都取决于TaskScheduler想怎么执行你的请求。

7. Q:我设计了一个公开的API要返回一个task,我应该返回一个尚未开始的task么?

    A:不要这么做。(这里把这个问题和#1、#2区别对待是因为#1和#2是真的想创建一个task之后可能选择不开始它。大家不要以为非得违背设计意图的开始一个不想开始的task之后返回)

那么,通常的来讲如果你调用的是一个同步方法,那个方法肯定是你一调用就开始执行的。那么在返回一个task对象的异步方法的场合,你可以认为task就是未来终将会完成的异步方法,那并不改变一个事实:通过这个方法的调用,相应的操作应该已经开始执行了。因此,如果你返回一个尚未开始的task从语义上来讲就很奇怪。

所以如果你在方法内部使用构造器创造了一个task,那么在返回它之前记得调用Start,否则可能引起死锁或者类似的情况,因为消费者会期待着你返回的task终将完成,但如果你根本没开始这个task那它当然也就无从完成。有些框架甚至允许你通过一个方法或者委托神马的来指定一个检查,当你启用了这个检查,框架会检查返回的task的状态,如果尚处在Created状态会抛异常。

8. Q:说了半天我到底应不应该首先调用构造器创造一个task然后调Start呢?

    A:对于大多数场合,你蛮好还是直接调用Task.Run或者TaskScheduler.StartNew吧,如果你的需求仅仅是让调度器帮你异步执行一段委托。这样不仅代码少,性能也好(如#5所述),而且减少了出错的几率(比如你忘了调Start神马的)。

当然构造器+Start方法也有其用武之地。比如你派生了自己的Task类型,那你就需要Start方法来真正把你的对象放入队列。再来看一个高级点例子:如果你想要在task的委托里使用这个task对象

Task theTask = null;
theTask = Task.Run(() => Console.WriteLine(“My ID is {0}.”, theTask.Id));

发现破绽了么?这儿有个竞态。当你调用Task.Run时,一个新的task对象被创建出来并被放入TaskScheduler的队列,如果当时线程池很闲,也许立刻就会有个线程来执行这段委托,这个线程会访问由主线程创建的theTask对象,从而存在一个竞态。想避免这种情况,只要把构造和开始分开执行就好了

Task theTask = null;
theTask = new Task(() =>Console.WriteLine(“My ID is {0}.”, theTask.Id));
theTask.Start(TaskScheduler.Default);

现在就可以保证在委托线程访问theTask对象之前主线程已经完成了对它的赋值

posted @ 2012-02-04 16:21 jiaxingseng 阅读(982) 评论(0) 编辑

WPF纯新手,之前拿WPF当WinForm一样的用过一两次,那时候对WPF是啥完全没有加以了解,就当WPF=WinForm的background code+xaml版的ASP.NET

这次准备开始做一个WPF项目,领导希望xaml和代码尽可能的分离,才找了本《WPF 4 Unleashed》看了下,然后简单了解了下Prism和MVVMLight就准备动手啦~~

貌似stackoverflow上对MVVMLight还比较赞,就准备用这个,结果第一次用就orz了,写出一点初步的心得给组里其他WPF初学者看一下,也请园子里的高手多指教。

■安装相关

我用的安装包,一切安装顺利,结果尝试新建一个MVVMLight Application的时候说项目模板(ProjectForTemplate.csproj) 找不到。

解决办法是到报错那个目录(C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplatesCache\CSharp\Windows\Mvvm\MvvmLight.WPF4.zip)下把MvvmLight.WPF4.csproj重命名就好了-v-

顺便说一下我也下了手动安装的那个zip包,好像文件名是没有问题的,下次尝试手动安装好了

之后是code snippets,好像不会像prop之类的那样有智能感知啊?从code snippets manager那里也确实找到了,在Snippets\CSharp下面,是不是应该挪到Visual C#下面?不知道了。。。求帮助

■ ViewModel相关

生成这种代码是要闹哪样啊 囧

                // Remove one of the two calls below
                throw new NotImplementedException();

                // Update bindings, no broadcast
                
//RaisePropertyChanged(UserIDPropertyName);

                
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                
//RaisePropertyChanged(UserIDPropertyName, oldValue, value, true);

我还没有理解所谓broadcast在这里做什么用,是一种类似于总线的设计?但是单从API设计来看我总会觉得这两个方法有一个内部调用关系的,于是我发现这两个方法都可以重载的时候我好惊讶- -

另外为了写个属性弄出这么一堆代码,也没给生成个region神马的看起来实在很头疼。。。就不能参考那个神马NotifyWaver(名字好像更长些?没记住。。。)的做法编译后织入么 

■ Messenger相关

这个才是我真正想吐槽的地方啊!

为神马Messenger比IMessenger公开的方法多啊!虽然这个也说得过去,但ViewModelBase里的MessengerInstance为神马是IMessenger类型啊!这样的话不是逼着我用Messenger.Default么!提供MessengerInstance有咩用啊!

然后Send方法还可以指定Target。。。我看例子中都是指定了一个View。。。这样ViewModel怎么和View分离啊!囧死了

最后为了一个Navigation要写这样的代码。。。

某ViewModel的某Command

    Messenger.Default.Send("XXXX""NavigationRequest"); 

某View

            Messenger.Default.Register<string>(this"NavigationRequest"
                                               , action =>
                                                     {
                                                         if (action.Equals("XXXX",
                                                                           StringComparison.InvariantCultureIgnoreCase))
                                                         {
                                                             _mainFrame.NavigationService.Navigate(
                                                                 new Uri("/Views/DashBoard.xaml", UriKind.Relative));
                                                         }
                                                     });

要用一个字符串作"NavigationRequest" 为token。。。而且可以指定token的这个Send方法还不是IMessenger里的。。。 

 

呼,就到这里吧~ 

 

posted @ 2012-01-12 17:52 jiaxingseng 阅读(962) 评论(0) 编辑
摘要: 刚看了一篇文章,讲在java世界里析构方法可能引起的漏洞以及如何防范。 马上在C#中试了一下,发现.net也有同样的问题。代码如下1usingSystem;2usingSystem.Threading;34namespaceTestProj5{678classVulnerable9{10intvalue=0;1112publicVulnerable(intvalue)13{14if(value<=0)15{16thrownewArgumentException("Vulnerablevaluemustbepositive");17}18this.value=value阅读全文
posted @ 2011-10-11 23:37 jiaxingseng 阅读(645) 评论(3) 编辑
摘要: 两天前Rob Ashton写了一篇博客CQRS is too complicated,实际内容是说CQRS并不复杂,只是要看你怎么去实施(以及别把PPT整得太复杂)。 摘要如下(顺序有打乱,我自己怎么理解起来方便怎么总结-v-) 一说起CQRS,人们头脑中就是这样的东西 实际上,CQRS在高层次的意义上来说,就是要读写分离,跟事件溯源啊神马的并不一定有联系。 首先看这样一个...阅读全文
posted @ 2011-09-30 14:09 jiaxingseng 阅读(1449) 评论(1) 编辑
摘要: NH的官网今天出了两篇blog,讲如何使用NH3.2的mapping by code,不过都弱爆了,推荐直接看Fabio Maulo的blog去(一、二) 简单的说,NH的mapping by code有三种方式 直接为每个entity类调用ModelMapper.Class方法 Conformist映射,也就是class by class Convention,当然约定是可以被explicit mapping所覆盖的 本文展示第二三种混合的方式,也就是使用convention,然后覆盖。 首先,使用Convention NH3.2中,使用Convent...阅读全文
posted @ 2011-09-06 10:08 jiaxingseng 阅读(2096) 评论(1) 编辑
摘要: 很久没有更新blog了,最近都在忙些私人的事儿,肚子里没货当然就没得写。今天这篇也不是什么心的技术心得,其实就是一个新闻:EF 4.1 Update 1 Released摘抄部分内容如下TitleIntroduction of new types to facilitate design-time tools for Code First.Update 1 introduces a set of ...阅读全文
posted @ 2011-08-01 00:25 jiaxingseng 阅读(853) 评论(1) 编辑
摘要: 写系列的上一篇已经是很久之前的事儿了= =在此期间,EF 4.1的RTW都已经出来了,NH 3.2的Alpha已经2了。。。其实不是我懒,工作中也在一直使用EF 4.1。主要是上次承诺过的一个Update功能搞不定= = 总之这一次的目标是 实现一个完整的IRepository(添加增删改能力) 领域对象的继承 事物 首先来看IRepository 我的接口如下 应该算是一个最基本的仓储接口了...阅读全文
posted @ 2011-04-22 15:12 jiaxingseng 阅读(4461) 评论(15) 编辑