Windows Phone 7 在美國時間 10/11 號正式發表了,如果還沒有看過的朋友,可到 https://www.microsoft.com/presspass/presskits/windowsphone/videogallery.aspx重溫當天的精彩內容。

 同一時間,過去用來發布 XNA 遊戲到 XBOX 的管道 XNA Creator Club 與發佈 Windows Phone 手機應用程式的 Marketplace Portal 合而為一,變成單一的入口網站 APP HUB。過去每年要繳兩次美金 99 塊的費用, 現在開發人員只要每年繳一次年費,就可以同時發布遊戲到 XBOX 或 Windows Phone 手機上,即使在這個時間點,開發人員還無法上傳台灣可以購買的 XNA 遊戲,台灣的 XBOX 玩家也無法付費購買這些 XNA 遊戲,但筆者相信這一天很快就會來臨。
 當讀者看到這一期電子報的時候,或許都可以在市面上看到 Windows Phone 7 手機了,為此我們也和每一位開發專家加緊趕工,努力的讓更多的技術文章出現在 https://msdn.microsoft.com/zh-tw/windowsphone/ff955788.aspx敬請期待。對了,在撰寫這篇文章的時候,筆者正使用由 https://zune.net 下載的 Zune Software 撥放音樂,Zune Software 除了是一個有質感的影音播放軟體之外,它也是 Windows Phone 7 同步 音樂/相片/影片/軟體 的重要橋梁。

 如果您在安裝 Zune Software 之後,無法看到已經在 Marketplace 上架的各種 Windows Phone 7 軟體的話,可以參考保哥的的兩篇文章

希望大家用的愉快!

SQL Azure 資料同步化技術
 SQL Azure 為雲端上的 SQL Server 資料庫,是基於 Windows Azure 平台能力所開發的雲端資料庫服務,與 Windows Azure 許多服務相同,都擁有高度的 Scale-Out 的能力,以及在雲端環境內強大的運算與儲存能力,而透過 SQL Azure 平台的特性,企業可以應用 SQL Azure 作為企業交換資料的中繼站,或是運用它作為服務前端 OLTP 應用程式的資料儲存位置,並與本地系統的資料庫或資料倉儲進行資料的同步化(Data Synchronization)。然而基於 SQL Azure 設計上的特性,傳統最廣為 SQL Server DBA 所使用的資料庫複製(Database Replication)無法在 SQL Azure 上使用,因此必須另外使用別的方法來處理資料同步的問題。唯一可以在 SQL Azure 和 SQL Server(或另一個 SQL Azure)之間進行資料同步的作法,就是寫程式來處理。
 所幸,微軟在同步化處理的領域中,早已發展出一套標準作法,並且將此作法開發成基礎功能,稱為 Microsoft Sync Framework,最新的版本是 2.1,它主要分為三個部份,最底層的是各式資料的供應者,Sync Framework 目前支援來自檔案系統(Microsoft.Synchronization.Files.dll)、資料庫(Microsoft.Synchronization.Data.dll)、輕量級資料(Microsoft.Synchronization.MetadataStorage.dll)以及作為發展同步化能力的簡單提供者(Microsoft.Synchronization.SimpleProvider.dll)等;中層是管理資料之間同步化走向的流程控制層(Orchestration),由 Microsoft.Synchronization.dll 的類別提供,所有的資料交換方向與步驟都經由此層管理;最上層則是處理同步化的控制器(Controller),由應用程式開發人員所撰寫,主要是啟動同步化流程以及應用 Orchestration 操縱資料同步流程的工作。
 要使用 Sync Framework 開發同步化應用程式時,開發人員要做的工作是撰寫 Orchestration 處理資料同步的程序,如果要同步的資料雙方都是相同且被 Sync Framework 所支援的話,那麼撰寫 Orchestration 的工作將會更簡單,SQL Azure/SQL Server 間的同步化就是因為 Sync Framework 對 SQL Server 的直接支援,因此可以大幅降低撰寫 Orchestration 所需要的工作量。下列程式碼即是一個簡單的 SQL Azure/SQL Server 資料庫同步化的程式碼:
[C#]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.Data.SqlClient;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization;
 
namespace SQLAzureDataSync
{
    class Program
    {
        public static string sqlazureConnectionString =
@"Server=[Your SQL Azure Server].database.windows.net;
Database=AdventureWorksLTSQLAzure;
User ID=[Your SQL Azure User Name]@[Your SQL Azure Server];
Password=[Your SQL Azure Password];Trusted_Connection=False;Encrypt=True;";
        public static string sqllocalConnectionString =
@"Server=(local);Database=AdventureWorksLT2008;Trusted_Connection=True";
        public static readonly string scopeName = "alltablesyncgroup";
 
        static void Main(string[] args)
        {
            // Test if input arguments were supplied:
            if (args.Length == 0)
            {
                System.Console.WriteLine("Please enter an argument.");
                System.Console.WriteLine("Usage: SyncTest.exe -setup");
                System.Console.WriteLine("        SyncTest.exe -sync");
            }
            else if (args[0] == "-setup")
                Setup();
            else if (args[0] == "-sync")
                Sync();
        }
 
        public static void Setup()
        {
            try
            {
 
                SqlConnection sqlServerConn = new SqlConnection(sqllocalConnectionString);
                SqlConnection sqlAzureConn = new SqlConnection(sqlazureConnectionString);
                DbSyncScopeDescription myScope = new DbSyncScopeDescription(scopeName);
 
                DbSyncTableDescription Customer =
SqlSyncDescriptionBuilder.GetDescriptionForTable("Customer", sqlServerConn);
                DbSyncTableDescription Product =
SqlSyncDescriptionBuilder.GetDescriptionForTable("Product", sqlServerConn);
 
                // Add the tables from above to the scope
                myScope.Tables.Add(Customer);
                myScope.Tables.Add(Product);
 
                // Setup SQL Server for sync
                SqlSyncScopeProvisioning sqlServerProv = new SqlSyncScopeProvisioning(sqlServerConn, myScope);
                if (!sqlServerProv.ScopeExists(scopeName))
                {
                    // Apply the scope provisioning.
                    Console.WriteLine("Provisioning SQL Server for sync " + DateTime.Now);
                    sqlServerProv.Apply();
                    Console.WriteLine("Done Provisioning SQL Server for sync " + DateTime.Now);
                }
                else
                    Console.WriteLine("SQL Server Database server already provisioned for sync " + DateTime.Now);
 
                // Setup SQL Azure for sync
                SqlSyncScopeProvisioning sqlAzureProv = new SqlSyncScopeProvisioning(sqlAzureConn, myScope);
                if (!sqlAzureProv.ScopeExists(scopeName))
                {
                    // Apply the scope provisioning.
                    Console.WriteLine("Provisioning SQL Azure for sync " + DateTime.Now);
                    sqlAzureProv.Apply();
                    Console.WriteLine("Done Provisioning SQL Azure for sync " + DateTime.Now);
                }
                else
                    Console.WriteLine("SQL Azure Database server already provisioned for sync " + DateTime.Now);
 
                sqlAzureConn.Close();
                sqlServerConn.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
 
        public static void Sync()
        {
            try
            {
 
                SqlConnection sqlServerConn = new SqlConnection(sqllocalConnectionString);
                SqlConnection sqlAzureConn = new SqlConnection(sqlazureConnectionString);
                SyncOrchestrator orch = new SyncOrchestrator
                {
                    LocalProvider = new SqlSyncProvider(scopeName, sqlAzureConn),
                    RemoteProvider = new SqlSyncProvider(scopeName, sqlServerConn),
                    Direction = SyncDirectionOrder.UploadAndDownload
                };
                Console.WriteLine("ScopeName={0} ", scopeName.ToUpper());
                Console.WriteLine("Starting Sync " + DateTime.Now);
                ShowStatistics(orch.Synchronize());
 
                sqlAzureConn.Close();
                sqlServerConn.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
 
        public static void ShowStatistics(SyncOperationStatistics syncStats)
        {
            string message;
 
            message = "\tSync Start Time :" + syncStats.SyncStartTime.ToString();
            Console.WriteLine(message);
            message = "\tSync End Time   :" + syncStats.SyncEndTime.ToString();
            Console.WriteLine(message);
            message = "\tUpload Changes Applied :" + syncStats.UploadChangesApplied.ToString();
            Console.WriteLine(message);
            message = "\tUpload Changes Failed  :" + syncStats.UploadChangesFailed.ToString();
            Console.WriteLine(message);
            message = "\tUpload Changes Total   :" + syncStats.UploadChangesTotal.ToString();
            Console.WriteLine(message);
            message = "\tDownload Changes Applied :" + syncStats.DownloadChangesApplied.ToString();
            Console.WriteLine(message);
            message = "\tDownload Changes Failed  :" + syncStats.DownloadChangesFailed.ToString();
            Console.WriteLine(message);
            message = "\tDownload Changes Total   :" + syncStats.DownloadChangesTotal.ToString();
            Console.WriteLine(message);
        }
    }
}
 這個簡單的程式碼分為兩個部份,一個是準備資料結構的程式碼,由 Setup() 程式來處理,它會呼叫 SqlSyncDescriptionBuilder.GetDescriptionForTable() 取得來源資料庫的表格描述資料(Data Schema),接著利用 SqlSyncScopeProvisioning.Apply() 將描述資料的指令碼送到目標資料庫進行處理,以同步來源與目標資料庫的資料表。
NOTE
若想知道 Apply() 傳了什麼樣的指令到目標資料庫,你可以使用 SqlSyncScopeProvisioning.Script() 方法取得指令碼。
 另一個則是實際執行資料同步的程式碼,由 Sync() 程式來處理,由於 Sync Framework 已包含完整的 Orchestration 機制,所以程式碼非常簡單:
[C#]
SqlConnection sqlServerConn = new SqlConnection(sqllocalConnectionString);
SqlConnection sqlAzureConn = new SqlConnection(sqlazureConnectionString);
SyncOrchestrator orch = new SyncOrchestrator
{
    LocalProvider = new SqlSyncProvider(scopeName, sqlAzureConn),
    RemoteProvider = new SqlSyncProvider(scopeName, sqlServerConn),
    Direction = SyncDirectionOrder.UploadAndDownload
};
Console.WriteLine("ScopeName={0} ", scopeName.ToUpper());
Console.WriteLine("Starting Sync " + DateTime.Now);
ShowStatistics(orch.Synchronize());
 
sqlAzureConn.Close();
sqlServerConn.Close();
 
 同樣的程式碼也可以使用 SQL Azure/SQL Azure 之間的同步化,別忘了 SQL Azure 的特性就是只要修改連線字串就能使用,無須修改資料存取的程式碼,所以 Sync Framework 內的程式也幾乎不用修改就能相容並在 SQL Azure 上執行。
 
NOTE
若需要在大型資料庫中使用這支同步化程式,則你需要在目標資料庫的提供者中加入兩個設定,一個是 MemoryDataCacheSize(使用記憶體的大小),另一個是 ApplicationTransactionSize(批次交易的大小),以控制在大量資料庫同步時的交易筆數,以避免交易時間太長導致 SQL Azure Gateway 因連線時間太長而自動將連線關閉。
參考資料:

Q:要如何將 DB 截取出來的資料,轉出成 htm 的檔案格式呢?

Q:請教有關 T-SQL 的 QUOTENAME() 函數..

 
 
創造 Windows Azure 的 HTTP Session Router(英文)
Windows Phone 7 應用程式範例集(英文)
 
 
 

Visual Studio 2010 邊做邊學系列:

 

最新 Office 開發影片 (含中文字幕):

https://msdn.microsoft.com/en-us/magazine/gg232773.aspx
 
Silverlight 4 的新功能與改進4(英文)
Microsoft 軟體開發日 – Visual Studio 2010 Ultimate 的應用
10/29 @ 台灣微軟 7A/7B

Microsoft 軟體開發日 – Visual Studio 2010 Ultimate 的應用
11/03 @ 台灣微軟 7A/7B

Imagine Cup 微軟潛能創意盃開跑了!
 
楔子:
  自從 iXXXXX那隻手機開始爆紅,使用者除了重視軟體的功能外,更在意起軟體的 UI (User Interface),因此程式開發人員與視覺設計人員間的合作日漸重要。
  然而,坊間仍不時聽聞程式與設計人員合作有磨合的情況,都不外乎是雙方在觀念與想法上有落差,導致溝通時出現嚴重問題。其實,這一切是都因為程式與設計人員均來自於不同的背景,使得在思考和溝通上無法如此契合。
  但各位千萬不要洩氣!為了反映廣大開發人員的心聲,小編特別重金禮聘了 B+ Studio 兩名當家花旦,陳大比和郭小比,共同企劃一味 msD2n 清涼帖,來跟各位分享關於雙 D 在生活及工作上的大小趣事,希望能透過觀念上的交流,讓雙方的合作更加順利,因此帖有助於替各位排排毒、降肝火,順便藥到病除,就敬請各位看官按時服用。

  程式與設計人員,大多來自不同的背景,因此在性格跟品味上,都有很大的差異。
  就像程式人員的工作環境總被幅射電腦和螢幕包圍,附近一定堆滿一疊一疊踢到腳就會殘廢的的磚塊書,甚至在離開座位時,還不忘抱上鍵盤一塊行動,在在都顯示了他們的對於技術上的熱情與執著。
  而設計人員則是一派優雅,桌面井然有序,配上簡單的幾幅相框點綴,總是在意穿著及愛 Mac電腦外型,也突顯他們在生活上的優雅,以及對於品味的堅持。
  雖然雙方在工作環境、衣著,甚至生活中在意的事都有不同,但在合作時,如果能先豎大耳朵,用心聽聽對方的聲音,這將會是一個很好的開始!(拍手)
 
  九月底的 tech ‧ days 完美落幕,不知道電腦前的你有沒有到現場接受資訊的洗禮、將和論壇上朋友們的討論延伸到會場、透過美麗的主持人或現場 SG 拿到不少贈品?

  遇到台灣微軟的大活動,小編當然不能放棄朝聖的機會,也聽了不少場的講座,而今天我想要分享一個很特別的講題「Designer & Developer 的完美合作-遊戲開發經驗分享」,是由承佑與育琦一同分享的,有別於一般演講的方式,透過兩人逗趣的互動將 Designer 與 Developer 間的相處方式呈現出來,也讓在場的我們對於另一個角色的扮演有更多的認識,因為多了那樣的了解,我覺得之後在工作上我可以多做些調整與溝通,可以讓工作更順利。

  在近兩個小時的課程中,小編大大拓展了視野,首先是「設計師並不是只會畫圖
  還有我們總是要重申程式人員不全都是宅男

  宅男是指對非主流文化有深入研究的人!寫程式很辛苦也很弔詭的,因為


就算程式裡沒 bug,編譯器也會有 bug
就算編譯器沒 bug,作業系統也會有 bug
就算一切都沒 bug,
當拿給使用者測試,還是會出現 bug。

  並想跟 Designer 說:不懂設計不代表我們不喜歡好設計!
  育琦提醒我們,簡單的設計不等於短時間內可以完成,並且以 Windows Phone 的設計是用黃金螺旋線來做例子,看似簡單的設計,其實是透過許多考慮與規劃。課程中也讓我們了解向量格式與點陣格式的不同,之後在工作溝通上可以避免因為不瞭解而產生的誤會。

  承佑則提醒 Designer 不要以為有很多技術表示我們都懂,我們也是要多方面學習跟摸索的。而 Designer 與 Developer 都有個共通點,就是需要安靜的工作環境;我們都對細節處有強烈的執著;更重要的是,我們都希望「專案順利,軟體受歡迎!!」
  兩人提供以下幾格漫畫,描繪溝通上可能遇到的問題
  兩人建議我們可以將狀況分成
現況:程式人員會從小細節講起,但設計人員需要大方向
解決:先從大方向著手,再共同確認設計上的細節

將點子埋入夥伴的腦子裡,讓點子與夥伴們一起長大

  也因為育琦與承佑兩人的互動相當有趣,所以特別會後與兩人相約聊聊,並想跟 MSDN 電子報的各位做分享

陳承佑 & 郭育琦

Windows 多點觸控程式設計大賽冠軍,得獎作品「蒼蠅王」。 目前為「B+ Studio」負責人。

編:當初怎麼會想要參加多點觸控程式設計大賽?
 B+:因為當初想要為兩人多留點回憶,當作生日時送給自己的禮物。
編:在合作過程中常起爭執嗎?有沒有印象最深刻的一次?
 B+:每一次都很印象深刻!而且我們已經有點公私不分,連平常吃飯看到有不錯的點子可以使用,都會又討論起來!
編:什麼原因讓自己想要開工作室?取名的意思?
 B+:自己開工作室最主要是想趁年輕的時候,做些自己想做的事情。
 至於為什麼會取名 B+ Studio。其實是當初比賽時,想替自己做的遊戲掛個 logo,上面通常都會有個工作室的名稱麻!因此就想到我們兩個的英文小名裡都有一個 B,也覺得 B Plus 念起來還蠻順口的,就取了這個名字了。
 後來再想想,我們想做的休閒小遊戲,其實也是遊戲產業中最容易被忽略的一塊,有點像 B 級遊戲。因此這個名字也有另一層意義,就是我們希望維持良好水準,做出更好的休閒小遊戲,成為 B 級遊戲中的 B+。
 另外也可以呼應華人文化的講求謙卑,B+ 還不到 A,讓我們能時時警惕自己,要不斷地向前邁進。

編:請可愛的兩位跟我們MSDN電子報的訂閱戶一段話。
  B+:去做沒做過的事,暫時忘記其他人的眼光。因為只有自己,才能聽見自己的聲音。
忘了給 B+ Studio 讚一下 ,或點擊右邊圖示進入官網,隨時關注他們的新消息喔!
 
 
© 2010 Microsoft Corporation. 著作權所有,並保留一切權利。 使用規定 | 商標 | 隱私權聲明 | 取消訂閱