2010年8月27日 星期五

在 Exchange 2007 上的進行會議室管理

會議室、投影機等資源,在企業通常需要預約。如果有人已經預約了,就應該自動拒絕。這樣的需求普遍地發生在每個公司中。

以往在 Exchange 2003 的會議室管理,必須使用會議室的帳號登入某台有安裝 Outlook 的電腦,在會議的選項中設定。這個方式在 Exchange 2007 是行不通的。

那要如何在 Exchange 2007 上進行會議室管理呢?

其實,Exchange 2007 的設定就更簡單了。是使用該資源的帳號在 OWA 中登入並設定即可。步驟如下:

1  登入 OWA

2  在網頁右上角點擊「選項」連結

image

3  在左方的 Menu 中點擊「資源設定」

image

4  設定「資源排定選項」

重點在於勾選「自動處理會議邀請與會議取消通知」,並設定其下的選項。

image

其他的選項就自己看看吧!

5 記得儲存哦!

image

參考

管理資源排程

遇到 Nulls 時的排序方式

今天看到了一個 Nulls Last 的 Oracle 語法,順便回頭研究 SQL Server 上要如何實作。

問題

當查詢遇到了排序的欄位中有 Null 值時,要如何將 Null 值改排在前還是排在後。

SQL Server 版

SQL Server 總認為 null 值是比較小的值。當order by 的欄位中有 null 時,null 的資料會先列出。相反地, order by …. desc 時會最後列出。

如果要改變,只好搞一下小技巧

--排列時,field1為null 的最後才列出
select * from tableName
order by case when field1 is null then 1 else 0 end, field1 asc

Oracle 版

Oracle 則認為 null 值是比較大的值。

對於 null 值要如何排序,Oracle 的獨特的語法來解決。

select * from tableName order by field1 NULLS First;   --Null 值先列出。此為預設

select * from tableName order by field1 NULLS Last;  -- Null 值後列出。

結論

這個問題,SQL Server 還是可以做到,只是要想一下小技巧。 看來這個地方 Oracle 比較貼心呢! 。

2010年8月26日 星期四

Oracle 的字串比對

問題

我想要查詢資料庫的Schema資訊時,以下列語法查詢,卻查不到資料。為什麼?

select * from sys.ALL_TAB_COLUMNS
where owner = 'hr'

原因

原來,Oracle 是有分大小寫的。此與 SQL Server 的預設值不同。為了查詢,必須改成大寫才能找到資料。

select * from sys.ALL_TAB_COLUMNS
where owner = 'HR'
image

不分大小寫

查詢時,如何不區分大小寫呢?例如在一個新聞上稿的資料庫中,查詢一篇文章內有 SQL Server 這個字串時,就必須不區分大小寫。

原來 Oracle 有兩個設定,NLS_COMP 與 NLS_SORT

NLS_COMP

這個設定是用來字串比對用的,適用於 where 子句中。

可設定的值

  • BINARY : 所有比對是根據其字元的 binary 值來比對。所以一定會分大小寫。
  • ANSI:遵守 NLS_SORT 的設定。這是10g R2 以前的設定方式。10g R2 以後仍在,只是為了向前相容性。
  • LINGUISTIC:遵守 NLS_SORT 的設定。這是 10g R2 後的設定方式。

設定方式

任選一方式來設定:

  • 環境變數:SET(export) NLS_COMP=<binary|linguistic>
  • 在連線的 session中 內設定:ALTER SESSION SET NLS_COMP=<binary|linguistic>;

NLS_SORT

NLS_SORT 設定 order by 子句的排序方式。

可設定的值

  • BINARY : 所有比對是根據其字元的 binary 值來排序。
  • V$NLS_VALID_VALUES : All sorting is done in accordance to a named linguistic definition. This means that Oracle will sort in accordance to a particular locale (GERMAN, POLISH, FRENCH, etc.).These valid named definitions may be obtained by querying the V$NLS_VALID_VALUES where parameter = `SORT'. Just be aware that all the values in this view also have a hybrid definition by adding a suffix of _CI (case insensitivity

設定方式

  • 環境變數:SET(export) NLS_SORT=<valid_value>
  • 在連線的 session中 內設定:ALTER SESSION SET NLS_SORT=<valid_value>;

範例

不區分大小寫

alter session set NLS_COMP=LINGUISTIC; --遵照 NLS_SORT 的設定,即下面的不區分大小寫
alter session set NLS_SORT=BINARY_CI; -- 不區分大小寫
select * from sys.ALL_TAB_COLUMNS where owner = 'Hr'
執行結果如下

 

image

 

參考

2010年8月24日 星期二

.NET 平台上 ORM 工具的趨勢

ORM 工具的趨勢比較,可由 Google trends 看到一些端倪

http://www.google.com.tw/trends?q=nhibernate%2C+entity+framework%2C+linq+to+sql&ctab=0&geo=all&date=all&sort=0

目前來說, NHibernate 的使用比率仍然相當高,但 Entity Framework 的逐漸看漲,未來應可凌駕 NHibernate 之上。

在目前資料庫存取技術,我建議開始使用 ADO.NET Entity Framework了,畢竟這是微軟主推的資料存取技術。而目前ADO.NET Entity Framework尚未有大廠推出 Oracle 的 Provider。Oracle預計明年推出。目前如果要存取Oracle,只能使用 NHibernate,目前只有它才能存取 Oracle,技術也相對成熟。

clip_image002

2010年8月21日 星期六

NHibernate 資源

前言

NHibernate 沿自 Java 的Hibernate,並在 .NET 平台中建立自己的勢力。在 ADO.NET Entity Framework 尚未出現前,在 .NET 平台中的 ORM 確實是第一把交椅。

許多客戶都在使用 Oracle,而在資料庫存取上, 到目前為止,ADO.NET Entity Framework 尚未有免費(或大廠)所推出的 provider for Oracle。Oracle 也有計畫要推出,見 Entity Framework Oracle Provider?,但時程至少落在2011年年初。我實在等不及了。只好回過頭來看看  Nhibernate 有沒有好的解決方案。

當然,我才 study 約5天左右,實在沒有實戰經驗。僅將找到的下載與學習資源集中在此,方便自己與大家學習。

官網資源

NHibernate 的官網當然是最多資源的地方。而 Download 區就有一堆實用的功能。我目前使用 2.1.2 版。

NHibernate Contrib

NHibernate Contrib 算是 NHibernate 的好兄弟,推出一些好用的工具,可在這裡下載。

其中極力推薦 NHibernate Linq,將 LINQ 的語法帶到了 NHibernate 中。因此不必再使用 Criteria 或 Query By Example 等不自然的方式來查詢,而且功能有限。HQL 雖然強大,可是不支援 Compile time 的除錯,當然也沒辦法 Intellisence。改用  LINQ 語法容易維護多了。

其他資源

PS:
   其他資源找到了會陸續補上。

2010年8月20日 星期五

Visual Studio Scrum 1.0 安裝

安裝過程,可見

http://visualstudiomagazine.com/Articles/2010/07/27/Installing-Scrum-Process-Template.aspx?Page=1

安裝

這裡 下載並安裝程式

上載Process Template

執行 Visual Studio 2010的功能表「Team/Team Project Collection Settings/Process Template Manager」

image

點擊「Upload」鍵,選擇目錄「C:\Program Files (x86)\Microsoft\Microsoft Visual Studio Scrum 1.0\Process Template」完成上傳.

Web Portal

小組網站必須顯示統計報表,而每種 Process Template 都可能有自己的顯示方式。Scrum 就是一例。

請將C:\Program Files (x86)\Microsoft\Microsoft Visual Studio Scrum 1.0\Project Portal\Microsoft.TeamFoundation.SharePoint.Scrum.wsp 複製到 moss 網站伺服器下的一個子目錄中,例如 c:\temp\。

再來,以管理員身份執行 cmd

image

逐一執行下列指令

SET STSADM="%CommonProgramFiles%\Microsoft Shared\web server extensions\12\Bin\stsadm.exe"
%STSADM% -o addsolution -filename Microsoft.TeamFoundation.SharePoint.Scrum.wsp
%STSADM% -o deploysolution -name Microsoft.teamfoundation.sharepoint.scrum.wsp -immediate -allowGacDeployment
%STSADM% -o execadmsvcjobs
%STSADM% -o enumsolution

記得注意一下是否有錯誤的訊息哦!我在執行%STSADM% -o execadmsvcjobs花了相當長的時間(1小時多),原來是在進行掃毒,你的環境可能沒有這回事。

結果

天啊!Dashboard 竟然出現了下面的錯誤訊息。但其它地方到還是正常的。而 Dashboard 也大約在半小時後自動正常了,也不曉得是什麼原因。

image

 

20110119 註記

這次安裝了另一台 TFS,這是安裝的是中文版的 TFS。使用上述方法後 並建立一個新的 Team Project 後,發生了下面的錯誤

TF249033: 沒有可供此地區設定識別項 (LCID) 使用的網站範本。網站範本名稱是: TFS2010 Agile Dashboard。LCID 是: 1033

查了保哥的 TFS2010 安裝 Microsoft Visual Studio Scrum 1.0 流程範本 ,才知道需要安裝 WSS 3.0 的 language pack

但最後,還是失敗了。用改 WSSTasks.xml 中的 language=1028 才能成功。

2010年8月19日 星期四

Method Chaining

原本在開發程式的時候,一個物件的 instant 如果需要連續地執行某些動作時,程式會類似下面範例程式。

using System;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var c = new MyClass();
            c.Do1();
            c.Do2();
            c.Do3();
        }
    }

    internal class MyClass
    {
        public void Do1()
        {
            Console.WriteLine("Do1");
        }

        public void Do2()
        {
            Console.WriteLine("Do2");
        }

        public void Do3()
        {
            Console.WriteLine("Do3");
        }
    }
}

instance c 必須呼叫 Do1, Do2, Do3, instance c 必須寫三次 c., c., c.

Method Chaining 則是另一種物件行為的設計方式。將上述 MyClass 的 void Method 改回傳物件本身,就可以達到另一種呼叫方式。

using System;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            var c = new MyClass();
            c.Do1().Do2().Do3();
        }
    }

    internal class MyClass
    {
        public MyClass Do1()
        {
            Console.WriteLine("Do1");
            return this;
        }

        public MyClass Do2()
        {
            Console.WriteLine("Do2");
            return this;
        }

        public MyClass Do3()
        {
            Console.WriteLine("Do3");
            return this;
        }
    }
}

看到了嗎?可以改成 c1.Do1().Do2().Do3() 的方式來呼叫,是不是很簡潔呢?

使用 Method chaining 的 API,是源自 small talk 語言的習慣,近來的 jQuery 大量地使用這樣的設計,方便程式開發人員使用。

這樣也有個缺點,會造成程式可讀性較差。總地來說,還是優點較大呢。

2010年8月12日 星期四

使用 Ajax 方式取得 UserControl 的內容

同事問到,如何以 Ajax 的方式取得 UserControl 的內容。

問題

由於 UserControl 是無法單獨被客戶端所呼叫(Request),因此我們必須想個辦法將 UserControl 加到一個 Page內。

解決步驟

1 Web Service 回傳 UserControl 的內容

使用 Visual Studio (我使用 2010) 建立一個 Web Application,並加入一個 WebService。程式碼如下

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{
    [WebMethod(EnableSession = true)]
    public string GetUserControlHtml(string location)
    {
        var webServiceString = string.Format("Thread Id={0}, Time={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("HHmmss fffffff"));
        var page = new Page();
        var userControl = (UserControl)page.LoadControl(location);
        userControl.EnableViewState = false;
        var form = new HtmlForm();
        form.Controls.Add(userControl);
        page.Controls.Add(form);
        var writer = new StringWriter();
        HttpContext.Current.Server.Execute(page, writer, false);

        return webServiceString + "<br /> " + RemoveFormTagFromHtml(writer.ToString());
    }


    /// <summary>
    /// 移掉 Form Tag
    /// </summary>
    /// <param name="html"></param>
    /// <returns></returns>
    private static string RemoveFormTagFromHtml(string html)
    {
        return Regex.Replace(html, @"<[/]?(form)[^>]*?>", "", RegexOptions.IgnoreCase);
    }
}

過程大略是:手動建立一個 Page,Page 內加入一個 Form,Form 動態載入指定的 UserControl。使用 Server.Execute 取得 html 內容後,將 <form tag 移除,避免避免原 asp.net 網頁失敗。

2 寫 UserControl

今天的配角是 UserControl。UserControl並不難實作。我簡單的寫了兩個 UserControl,分別 Thread.Sleep 了2秒,3秒。

3 於呼叫網頁使用 Ajax 方式呼叫 ASP.NET Web Service

我再入成兩種方式來呼叫。一個是 ASP.NET AJAX,一個則是 jQuery。

3.1 使用 ASP.NET AJAX 呼叫 Web Service

加入一個 ScriptManager,並加入一個 ScriptReference 參考到剛剛建立的 WebService。利用動態產生的 javascript file (可使用 http://…/WebService1.asmx/jsdebug 取得內容)協助呼叫 ASP.NET Web Service

3.2 使用jQuery 的 .ajax 呼叫 Web Service

使用jQuery 大概是近來 Web 技術的顯學吧。為了方便未來的 ASP.NET MVC的使用,還是乖乖的學一下吧。

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication3._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
    <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            var datestring = getNow();
            $("#div1").html("at client, " + datestring + "<br/>");
            getData("WebUserControl1.ascx", $("#div1"));

            datestring = getNow();
            $("#div2").html("at client, " + datestring + "<br/>");
            getDataByJquery("WebUserControl2.ascx", $("#div2"));
        });

        function getNow() {
            var today = new Date();
            return today.format("HHmmss ffffff");
        }
        function getData(controlLocation, container) {
            WebApplication3.WebService1.GetUserControlHtml(controlLocation,
                function (result) {
                    $(container).append(result);
                },
                function () { alert(error.get_message()); }
            );
        }

        function getDataByJquery(controlLocation, container) {
            var datestring = getNow();
            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "WebService1.asmx/GetUserControlHtml",
                data: "{'location': '" + controlLocation + "'}",
                dataType: "json",
                success: function (result) {
                    $(container).append(result.d);
                },
                error: function (error) { alert(error.responseText); }
            });
        }
    </script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/WebService1.asmx" />
        </Services>
    </asp:ScriptManager>
    <h2>
        Welcome to ASP.NET!
    </h2>
    <div style="border: 2px solid red">
        <h1>
            User Controll 1</h1>
        <div id="div1">
        </div>
    </div>
    <div style="border: 2px solid red">
        <h1>
            User Controll 2</h1>
        <div id="div2">
        </div>
    </div>
    <div id="result">
    </div>
</asp:Content>

4 測試

測試時發現狀況還不錯。雖然同時發出 Request, 約2秒後得到UserControl1 的內容,但 UserControl2卻在約略在 5.5 秒後才得到內容,而非3秒。為什麼?

image

5 Session 造成 lock,因而 Delay

原來是步驟1中,[WebMethod(EnableSession = true)] 這個 true 所造成的。改成 EnableSessioin = false後,網頁測試結果如下

image
這樣就符合我們的期待了。

沒事最好還是不要用 Session。

範例下載

2010年8月10日 星期二

WPF 學習:透明應用程式

有些程式有獨特的風格,例如透明應用程式就是一例。那要如何寫出這類風格的程式呢?

Xaml

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" AllowsTransparency="True" WindowStyle="None"
        Background="Transparent" MouseLeftButtonDown="Window_MouseLeftButtonDown">
    <Grid>
    <Ellipse Opacity="0.5" Fill="Green">
      <Ellipse.BitmapEffect>
        <DropShadowBitmapEffect />
      </Ellipse.BitmapEffect>
    </Ellipse>
  </Grid>
</Window>

重點
  1. Window 的 AllowsTransparency 必須設為 True,否則無法呈現透明。
  2. Window 的 WindowStyle 必須設為 None。否則會出現例外。
  3. Window 的 Background 必須設為 Transparent,以顯示透明效果。
經過這三個設定後,程式一跑,就看不到任何的程式內容了。所以我們必須加上內容。如上面範例所示,我增加了一個 半透明的Ellipse,並且以 DropShadowBitmapEffect 產生些微的陰影效果。 再來,為了讓應用程式的 Window 可以移動,我加了MouseLeftButtonDown 的事件處理器。
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  this.DragMove();
}
這樣,我們就可以拖動視窗了。範例執行畫面如下。

image

2010年8月9日 星期一

AppFabric Cache Exception.

問題

我在寫入一個大量資料的Cache時,發生如下的錯誤

Microsoft.ApplicationServer.Caching.DataCacheException: ErrorCode<ERRCA0016>:SubStatus<ES0001>:The connection was terminated, possibly due to server or network problems or serialized Object size is greater than MaxBufferSize on server. Result of the request is unknown.

由錯誤訊息得知可以透過 MaxBufferSize 來解決問題。

解法步驟

解決方法,必須同時在 Server 端及 Client 端增加 MaxBufferSize 的設定。

首先是 Server Side

Server Side

Export Cluster Config


Export-CacheClusterConfig -File c:\temp\cluster.config

將Cluster 的設定匯出到一個 xml config 檔。此處我命名為 cluster.config

增加 transportProperties 的設定

依照 Application Configuration Settings 的建議,在上一步驟的cluster.config 增加下面的設定

匯入並套用設定

在匯入設定前,必須先停止 Cluster。匯入設定後,記得再啟動 Cluster。
Stop-CacheCluster
Import-CacheClusterConfig -File c:\temp\cluster.config
Start-CacheCluster

再來是 Client Side

Client Side

在 Client config 加入 transportProperties 設定

<?xml version="1.0"?>
<configuration>
    <configSections>
        <section name="dataCacheClient"
                    type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
                        Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, 
                        Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                     allowLocation="true"
                     allowDefinition="Everywhere"/>
    </configSections>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
    </startup>
    <dataCacheClient>
        <hosts>
            <host name="localhost" cachePort="22233"/>
        </hosts>
        <transportProperties maxBufferPoolSize="268435456" maxBufferSize="83886080" />
    </dataCacheClient>
</configuration>

Share with Facebook