2010年6月13日 星期日

TortoiseSVN 常用指令介紹 Part 2. SVN Update

每天開發專案的第一事應該就是將前一天其他組員所開發的結果更新至自已的電腦中。

SVN 的指令就是 SVN Update

image

Update 之後可能會出現三個狀況。

  1. 工作十分順利,昨天同組員所變更的項目並無衝突 (Conflict) 發生。Update 之後直接會將新的程式碼下載至你的工作目錄中。
  2. 不好,發生了衝突。但Merge的程式還是可以自動將程式合併。
  3. 哇!! 發生衝突了,而且又合併失敗。此時就需要手動的合併了!!

在十分順利的狀況之下,會出現類似以下的畫面,發現有人修改一個檔案並增加了另一個檔案,TortoiseSVN 會自動的將檔案更新。

image

如果說有發生衝突的話呢?? 當SVN 可以判別時,他會自動的將衝突合併,所以一般而言並不會造成我們的困擾。如下圖,在 SVN Update之後,他會自動的幫我們合併在一起

image

但如果說,無法自動合併的話呢?? 那就得手動來判別了。

當無法自動合併時會出現以下的訊息。此時就需要一些手動的操作來解決衝突問題了。

image

我們會發現有衝突發生時檔案的圖示會有一個驚嘆號出現 image

我們必需選擇 TortoiseSVN –> Edit conflicts

image

image

Merge 的操作這裡先不提。基本上它會把檔案上不同的部份全部列出來來讓我們比較合併。

但這樣子的狀況並不會常常發生,所以也不用太擔心。

合併完成後再選擇 TortoiseSVN –> Resolved 告知 SVN 我們已解決了衝突的問題了。

再將我們所做的變更 Commit 進 SVN 中便算完成。

image

經過 Update 之後我們就算是取得了最新的程式副本了,那就可以開始一天的工作了。


這一篇介紹的指令有

  • SVN Update
  • TortoiseSVN –> Edit conflicts

TortoiseSVN 常用指令介紹 Part 1.

當我們使用 SVN 來當作我們版本控制的工具時,我們必需先得知我們版本庫的所在位置。也就是 URL of repository。

第二步就是要設定我們的 工作目錄 以下就來介紹如何設定

SVN CheckOut

1.先在所要工作的目錄上按右鍵,選擇 SVN CheckOut

image

2.設定 URL of repository 至你的 Repository URL後,按下 OK

image

3.SVN 會將目前 Server 上的資料 download 下來,目前只有三個目錄。

image

目錄的圖示也會變成下面的樣子,綠色的勾勾代表目前這個工作目錄與 SVN Repository 上的相同

image

順便介紹一下 TortoiseSVN 的圖示

Explorer showing icon overlays

基本上,建議在下班前的狀態都是 Normal 的狀態。

4.接下來在工作目錄裡建立一個目錄 這個範例裡是 D:\Temp\TestForSVN\FirstApp

image 目錄的圖示會變成一個問號,代表的是這個目錄還沒加到 SVN 中。

5.假設我們的專案產生了一些檔案,接下來我們要將它們加入SVN中。

在剛剛產生的目錄按右鍵選 TortoiseSVN –> Add

image

因為有些檔案是不需要加入 SVN 中的,所以我們要將它們取消圈選。

image

按下 OK 後會將檔案 加入 SVN 中。可以看到我們這一次加了 8 個檔案。

image

請注意,此時我們所做的更動還沒 Commit 進 SVN 中。所以目前目錄的狀態是 Added 要再 Commit 之後才算完成。

image

在目錄上按右鍵選擇 SVN Commit 將我們剛剛的變更寫入 SVN 中

image

我們在剛剛已經有選擇過要加入SVN中的檔案了,所以在這裡不用再選一次。直接按下 OK 就好了

image

按下 ok 後會顯示出結果。 大工告成。

image

我們也會發現,現在的目錄變成了normal 的狀態(有時目錄的狀態不會馬上更新,請等一下或是做 Refresh便可)

image

所以今天介紹的指令有

  1. SVN Check Out -> 初始化檢出 - 設定工作拷貝
  2. SVN Add -> 將新的項目加入 SVN 中
  3. SVN Commit -> 提交修改

2010年4月22日 星期四

在 Visual Studio 中使用 SVN

上次在安裝完了 svn 之後,接下來就是要讓 Visual Studio 整合 svn。

網路上有一些套件可供使用。在這裡我們所採用的是 ankhsvn,下載之後直接安裝就可以了。

我們簡單的介紹一下如何在 Visual Studion 中如何使用。

首先先新增一個專案,我們會發現到,多了一個 Add to Subversion 的選項

image

按下 ok 後會出現加入 svn 的畫面,將 Repository Url 改為你 svn 的位置。在這裡是 svn://svnserver/test/

image

選好之後會請你輸入帳號密碼,就照我們之前在 passwd 那個檔案中所設定的,我們設定的是

user : testuser

password : testpw

輸入完畢之後,會出現下面的畫面,他會在你選的目錄下再建立一個 Project Name 的目錄。所以不用特地再建立新的目錄。

image

建立好之後可以看到我們的 solution windows 中的檔案多了一個符號 image 這代表這是一個新的檔案,尚未 Commit 至 repository 中。

image

在 solution 上按右鍵 選擇 Commit Solution Changes 將 solution Commit 進去

image

之後檔案的狀態會更改為image 此時如果有對檔案做任何的修改的話狀態會更改為 image

image

修改完畢之後記得要再 Commit 進 svn 中。但在 commit 之前千萬要記住,要先 compile 過,不要將有問題的 code commit 進 svn. 這樣會照成大家的麻煩。

2010年4月21日 星期三

Install SVN on DS1010+

DS1010+ 是 Synology NAS 產品,性能似乎十分的強大。網路上也有許多可以應用的資源。最近公司需要使用到版本控管的功能。於是便有想在 DS1010+ 上安裝 SVN 的念頭。因為 DS1010+ 基本上是跑 linux 的系統,再加上它所使用的 CPU 是 Intel ATOM 的系統,所以與之前 Synology 所提供的 Package 不同。著實讓我花了不少時間。

以下就是我安裝的過程

所有的資料都來自於 Synology 的wiki  Step-by-step guide to installing Subversion。有興趣的人也可以直接上去參考。

1. Enable CLI on your Diskstation  將啟動 SSH 功能打勾

image

2. 建立啟動 subversion 服務的使用者

因為diskstation 是跑 Linux 系統的,所以 subversion 需要一個啟動它的使用者,這裡所使用的是 svnowner。記住,這個使用者的密碼可以要設的複雜一點。而且就算你忘了也沒關係。因為基本上我們是不會用到他去做登入的動作。image

 

3.建立一個共用資料夾供 svn 使用。

在這裡我所使用的是 svn 目錄,記得要給 admin 及 svnowner 有讀寫的權限。並將其他所有的權限都移除。

4. 安裝 ipkg bootstrap

在這裡我參考了另一個討論串(IPKG for DS1010+)及另一個Blog,Diskstation 的預設是沒有 ipkg 的(ipkg 是在嵌入式裝置上最見的套件管理系統),我們需要利用 ipkg 來安裝我們所需要的套件。

    1. 利 用 putty 進入到 DS1010+ 中的命令模式。
    2. get the script from internet
        wget http://ipkg.nslu2-linux.org/feeds/optware/syno-i686/cross/unstable/syno-i686-bootstrap_1.2-7_i686.xsh




    3. run it   

        sh ./syno-i686-bootstrap_1.2-7_i686.xsh




    4. reboot


    5. after reboot, login with root。 變更 ipkg 所查詢的位址

        vi /opt/etc/ipkg.conf




    6. 在開啟檔案後加入以下紅色的文字,因為 DS1010+ 的cup 是 intel atom 系列的,所以我們要採用的是 syno-i686 的 Feed


    7. # Uncomment one of the following package feeds or resolve your arch
      # by visiting http://ipkg.nslu2-linux.org/feeds/optware/
      # src nslu2 http://ipkg.nslu2-linux.org/feeds/optware/nslu2/cross/stable
      # src fsg3 http://ipkg.nslu2-linux.org/feeds/optware/fsg3/cross/stable
      # src ddwrt http://ipkg.nslu2-linux.org/feeds/optware/ddwrt/cross/stable
      # src xwrt http://ipkg.nslu2-linux.org/feeds/optware/ddwrt/cross/stable
      # src whiterussian http://ipkg.nslu2-linux.org/feeds/optware/ddwrt/cross/stable
      # src oleg http://ipkg.nslu2-linux.org/feeds/optware/oleg/cross/stable
      # src ts72xx http://ipkg.nslu2-linux.org/feeds/optware/ts72xx/cross/stable
      # src/gz openwrt-brcm24 http://ipkg.nslu2-linux.org/feeds/optware/openwrt-brcm24/cross/u
      # src/gz openwrt-ixp4xx http://ipkg.nslu2-linux.org/feeds/optware/openwrt-ixp4xx/cross/u
      dest root /

      #option verbose-wget
      #
      # Proxy support:
      #
      #option http_proxy http://localhost:5865
      #option ftp_proxy http://proxy.tld:3128
      #option proxy_username <username>
      #option proxy_password <password>

      src syno-d1010 http://ipkg.nslu2-linux.org/feeds/optware/syno-i686/cross/unstable






    1. 更新 ipkg 的資料


    2. ipkg update
      ipkg upgrade


    3. 到這裡 ipkg 可說是可以使用了,接下來我們要開始來案裝 Subversion


    4. ipkg install svn




5. 設定 SVN 




    vi /etc/inetd.conf


  1. 加入下面的設定到最後一行


  2. svn stream tcp nowait svnowner /opt/bin/svnserve svnserve -i -r /volume1/svn


  3. svnowner 就是我們剛才所新增的使用者,/volume1/svn 就是我們剛才所新增的共用目錄。


  4. vi /etc/service


  5. 加入下面的設定到最後一行


  6. svn 3690/tcp #subversionsvn 3690/udp #subversion


  7. 重新開機 reboot


  8. 重新開機後要來設定 SVN 存放空間(Repository)的權限



    1. su svnowner
      cd /volume1/svn
      svnadmin create test


    2. 你可以將 [test] 改成你想要的名稱。經過以上的指令後會在svn 目錄中新增一個 test 的目錄,現在我們要經由編輯裡面的檔案來設定存取的權限


    3. vi /volume1/svn/test/conf/passwd


    4. 加入


    5. [users]
      testuser = testpw


    6. vi /olume1/svn/test/conf/svnserve.conf


      加入

      [general]

      anon-access = none


      auth-access = write


      password-db = passwd


      realm = I am your test repository







大功告成,接下來就是使用 svn client 去存取這個 Repository 了

2009年10月23日 星期五

ModelBinder In Asp.Net MVC

What is ModelBinder.
在 MSDN 中是這麼定義的

IModelBinder
Defines the methods that are required for a model binder.亙 費話

ModelBinder在 ASP.NET 中最主要的作用是讓POST回來的值在進入 Cotroller 之前可以先做一點整理。讓 Controller 可以直接使用已整理後的 Class 而不是一堆 Form 上面的資料

How.
要使用 ModelBinder 有幾個步驟
1. 建立 ModelBinder, 要 Implement IModelBinder
    public class Service1ModelBinder : IModelBinder
    {
        #region IModelBinder Members
 
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var request = controllerContext.HttpContext.Request;
 
            Service1 service = new Service1(new User())
            {
                Name = request["name"]

..... other fields you need

            };
 
            return service;
        }
 
        #endregion
    }

2.定義 這個 ModelBinder 是 Bind 那個Class,這個要寫在 HttpApplication 中,一般是 Global.asax.cs

        protected void Application_Start()
        {

            //ModelBinders
            ModelBinderDictionary binders = System.Web.Mvc.ModelBinders.Binders;
            binders[typeof(Service1)] = new Service1ModelBinder();
            RegisterRoutes(RouteTable.Routes);
        }

3. 改寫 Controller 的 method

        [AcceptVerbs("POST")]
        public ActionResult Index(Service1 service)
        {
            ViewData["Message"] = service.Name;
 
            return View();
        }
View 的 code 如下
    <% Html.BeginForm(); %>
        <input type="text" name="name" value="Service1" />
        <button type="submit">Submitbutton>
    <%Html.EndForm(); %>

如此一來,在我們按下按鈕時會先觸發 ModelBinder 再將 ModelBinder 過後的 object 送給 Controller

Reference

IPrincipal (User) ModelBinder in ASP.NET MVC for easier testing


IModelBinder Interface

2009年10月21日 星期三

Unity 學習筆記 in Asp.Net MVC

1.Container.Resolve(Type t)
Resolve an instance of the default requested type from the container.
會將所指定的 class 產生一個 instance 並且將 Constructor 中的 parameter 注入

        container.Resolve(typeof(HomeController))

        public HomeController(Service service, Service2 service2)
        {
            this.service = service;
            this.service2 = service2;
        }

container 會將 Service 及 Service2 注入到 HomeController 中
但有個地方值得注意的。就是如果 HomeController 的 Constructor parameter 的 type 是 interface 時,就必需要注冊
            container.RegisterType<IService, Service>();

否則會有錯誤產生

2. Singleton
底下以 RegisterInstance 的方來來注冊 IUser

        protected void Application_Start()
        {
            IUnityContainer container = new UnityContainer();
 
            container.RegisterInstance<IUser>(new User() { Name = "Unity" });
 
 
            CustomUnityControllerFactory factory = new CustomUnityControllerFactory(container);
 
 
            ControllerBuilder.Current.SetControllerFactory(factory);
 
            RegisterRoutes(RouteTable.Routes);
        }

HomeController
Constructor 中有兩個參數 Service1, Service2
    [HandleError]
    public class HomeController : Controller
    {
        Service1 service1;
        Service2 service2;
 
        public HomeController(Service1 service1, Service2 service2)
        {
            this.service1 = service1;
            this.service2 = service2;
        }
 
        public ActionResult Index()
        {
            ViewData["Message"] = service1.Message();
 
            ViewData["Message2"] = service2.Message();
 
            return View();
        }
 
        public ActionResult About()
        {
            return View();
        }
 
    }

Service1
在呼叫 Message 後會改變 User.Name 的值
    public class Service1 : IService
    {
        IUser user;
 
        public Service1(IUser user)
        {
            this.user = user;
        }
 
 
        #region IService Members
 
 
        public string Message()
        {
            string t = user.Name;
            user.Name = "Yes!! I'm Sigleton";
            return t;
        }
 
        #endregion
    }

Service2
    public class Service2 : IService
    {
        IUser user;
 
        public Service2(IUser user)
        {
            this.user = user;
        }
 
        #region IService Members
 
        public string Message()
        {
            return user.Name;
        }
 
        #endregion
    }
需注意的是 在 Service 的 constructor 中需以 IUser ,如以Class 來當為參數的話。unity會產生一個新的實體。


Reference
Unity framework with ASP.Net MVC Framework

2009年4月24日 星期五

Project to Posts ( Link to Sql sample)

由資料庫 投射到 實體的範例
在 oxite.LinqToSqlDataProvider 中的 PageRepository.cs
要 學起來

        private IQueryable<Page> projectPages(IQueryable<oxite_Post> posts)
        {
            return from p in posts
                   join u in context.oxite_Users on p.CreatorUserID equals u.UserID
                   let c = getCommentsQuery(p.PostID)
                   where p.State != (byte)EntityState.Removed
                   orderby p.PublishedDate descending
                   select new Page
                   {
                       ID = p.PostID,
                       Parent = getParentPage(p),
                       HasChildren = getHasChildren(p),
                       Creator = new User
                       {
                           DisplayName = u.DisplayName,
                           Email = u.Email,
                           HashedEmail = u.HashedEmail,
                           ID = u.UserID,
                           LanguageDefault = new Language
                           {
                               ID = u.oxite_Language.LanguageID,
                               DisplayName = u.oxite_Language.LanguageDisplayName,
                               Name = u.oxite_Language.LanguageName
                           },
                           Name = u.Username,
                           Status = u.Status,
                       },
                       Body = p.Body,
                       BodyShort = p.BodyShort,
                       Comments = new LazyList<Comment>(c),
                       Created = p.CreatedDate,
                       Modified = p.ModifiedDate,
                       Published = p.PublishedDate,
                       Slug = p.Slug,
                       State = (EntityState)p.State,
                       Title = p.Title,
                       CommentingDisabled = p.CommentingDisabled
                   };
        }