2010年9月27日月曜日

Project Euler(その3)

引き続きやってます。めでたくレベル2になりました。

Linqも、SelctManyやAggregateの使い方がわかってきた気がします。
一つわからないのが下の様なケース。TakeWhileやAggregateで出来そうな気もするんですが。どうするのがいいんだろう。

・合計がxを越えない範囲で列挙する。

あと、.NET Framework4でBigIntegerが追加されてることを知りました。便利。
#というか反則っぽいなぁ

2010年9月24日金曜日

Project Euler(その2)

image

今日も引き続き挑戦してました。18問目まで終了。

12問目がなかなか計算時間短縮が難しい。

2010年9月23日木曜日

Project Euler

Project Eulerなるものを知った。数学の問題をプログラムで解くらしい。
おもしろそうなので、登録してみた。
#そういえば、TopCoderに登録してそのままなことを思い出した。
http://projecteuler.net/

日本語のWikiもあり、問題も日本語化されているようだ。<やった。
http://odz.sakura.ne.jp/projecteuler/index.php?Project%20Euler

番号が若いうちは比較的簡単。出来るだけLinqを使って書くように心がける。
#でもLinqだと無駄が出やすい気がする。スピード重視なら、手続き指向になるのかなぁ。

image

とりあえず、今日は8問目まで。

2010年9月15日水曜日

Azureへのデプロイ(手動)

いい加減、Azureへデプロイです。

プロジェクトを右クリックメニューより発行を選択。
image
表示されたダイアログで、「サービスパッケージだけを作成」を選択しOKをクリックします。
image 
.cspkgファイルとcscfgファイルが作成されます。
image

これを、Azure環境にデプロイします。
まず、Windows Azure Developer Portal(http://windows.azure.com/)にアクセスします。その後、New Serviceをクリックします。
image
Hosted Servicesを選択します。
image
Service Labelと、Service Descriptionを入力します。適当でOK.
image
次にURLと、デプロイ場所を決定し、Createボタンをクリックします。
image
とりあえず、出来ました。そして、Deployボタンをクリック。
 image
Application Packageに.cspkgファイルを、Configuration Settingsに.cscfgファイルを設定。Deployment Nameを入力したら、Deployボタンをクリック。
image 
デプロイ完了です。最初は、Stoppedなので、Runボタンをクリックしアプリケーションを開始します。
image

しばらく、待つとデプロイが完了します。ステータスは次のように変更されます。
image
image
image

以上で、すべて完了。

2010年9月13日月曜日

開発環境での実行

油断すると、すぐ間隔が開いてしまって困ったことです。

前回の続きです。今回は、とりあえず実行するために、デフォルト設定で突き進みます。

まずは、プロジェクトの作成から。
VisualStudio2010を管理者モードで起動し(これ重要!いつも忘れます(^^;))、新しいプロジェクトの作成より、Windows Azure クラウドサービスを選択。
image 
プロジェクトには、とりあえず、ASP.NET Webロールを一つだけ追加。
image
すると、ソリューションが作成されます。
image
その後、いきなりF5で実行。ASP.NETで作成されたテンプレートページが表示されます。一見、普通のWeb開発と変わりません。
image
違いはというと、タスクトレイのアイコンぐらい
image
右クリックメニューより、Development Fabric UIとDevelopment Storage UIを表示することが可能です。
まずは、Development Fabric UI。
image
続いて、Develpment Storage UI。
image

以上で、ローカルでのAzureプロジェクトの実行は完了です。 次は、ようやくデプロイ。

2010年9月1日水曜日

Windows Azure Toolのインストール

昨日、Azureの申し込みを完了したので、今日は環境の整備。

Windows Azure Toolsをインストールします。
ダウンロードは、下記から。

「Windows Azure Tools for Microsoft Visual Studio 1.2」
http://www.microsoft.com/downloads/details.aspx?displaylang=ja&FamilyID=2274a0a8-5d37-4eac-b50a-e197dc340f6f

リンク先ページにある、注意事項を参考にしつつインストールしました。
Windows7(x64)×VS2010なので、↓だけ追加でインストール。
http://code.msdn.microsoft.com/KB981002

というわけで、環境の準備は終了。そして今日の作業も終了。
明日はサンプル作りたいな。

2010年8月31日火曜日

Windows Azure PlatformのMSDNサブスクリプション特典

MSDNサブスクリプションを利用中の方には特典が用意されています。詳しくは↓。
http://msdn.microsoft.com/ja-jp/subscriptions/ee461076.aspx

幸いにもPremiumの割り当てがあるので、申し込みを行ってみます。
入り口は、MSDNサブスクリプションのページから。

image

WIndows Azure プラットフォームのリンクをクリックすると、Microsoft Online Service カスターマー ポータルにサインインします。(アカウントがない場合は、ここで作成します。)

image

すると、ショッピングカートに商品が入っている状態に。あとは、同意するチェックボックスにチェックを入れて、購入手続きへ。(クレジットカード情報等を入力します。なぜか途中のValidationに引っかかって、何回か最初からやり直しましたが…)

image

あとは、サービスをアクティブにすれば終了。とりあえず、きょうはここまでか。

Azure始めたい。

行ってもいないTech・Edに影響されて、Azureの書籍を買ってしまいました。

とりあえず申し込みから始めるか…

2010年7月31日土曜日

Expression Studio 4

今更ですが、ダウンロード可能になってました。
http://www.microsoft.com/japan/products/expression/

さて試すか。

2010年6月30日水曜日

SQLServer Compact Edition

SQLServerCeで行ロックがかかっているかの実験。

using (var connection1 = new SqlCeConnection(Settings.Default.Setting))
using (var connection2 = new SqlCeConnection(Settings.Default.Setting))
{
connection1.Open();
connection2.Open();
var command1 = connection1.CreateCommand();
var command2 = connection2.CreateCommand();
using (var tran1 = connection1.BeginTransaction())
using (var tran2 = connection2.BeginTransaction())
{
command1.Transaction = tran1;
command2.Transaction = tran2;

command1.CommandText = "select * from table1 with (updlock) where id = 1";
command2.CommandText = "select * from table1 with (updlock) where id = 1";

using (var reader1 = command1.ExecuteReader())
using (var reader2 = command2.ExecuteReader())
{
while (reader1.Read() && reader2.Read())
{
Console.WriteLine(reader1.GetInt32(0));
Console.WriteLine(reader2.GetInt32(0));
}
}
}
}


確かに。

2010年6月24日木曜日

Visual Studio 2010 Pro Power Tools

Visual Studio 2010 Pro Power Toolsをインストールしてみた。
http://visualstudiogallery.msdn.microsoft.com/en-us/d0d33361-18e2-46c0-8ff2-4adea1e34fef
  • タブがカラフルになった

    image
  • タブの設定がいろいろ設定項目が増えている

    image
  • タブがピン留め出来る

    image
  • 参照の追加ダイアログが変わった(しかも早い)

    image
  • 現在の選択行がハイライトされる
  • HTMLコピーが出来る(↓)
    var list = new List<Class1>
    {
        new Class1{ Name = "abc"},
        new Class1{ Name = "def", Inner = new Class1{Name = "DEF"}},
        new Class1{ Name = "ghi", Inner = new Class1{Name = "GHI"}},
    };
  • トリプルクリックで一行選択

    Wordと一緒ですな。
  • Ctrl+クリックで定義で移動

    eclipseでそんな操作ができたような
  • Ctrl + Alt + ] で = がそろう(便利?)
  • 縦位置のガイドラインが追加出来る
など盛りだくさん。
あと、Alt+↑ とか Alt+↓とかで、コード移動が出来るみたいなのだが試してもよくわからなかった。

2010年6月1日火曜日

スカラプロパティーに外部キーを追加する

Entity Framework4では、外部キーをスカラプロパティーとして公開することが出来ます。

外部キーの使用 (Entity Framework)
http://msdn.microsoft.com/ja-jp/library/ee794150.aspx

でも、追加方法がよくわからずはまったので備忘録。

①追加からアソシエーションを選択すること。
(ツールボックスからではダメ。ここではまった。)
image

②外部キープロパティーの追加にチェックを付ける
 image
③プロパティーが追加されます。
image 

ところで、追加されたプロパティーが、どのアソシエーションに関連しているかを確認する方法がない?

2010年5月26日水曜日

WPF - レイアウトのリセット

最近、またWPFの入門中。(何度目?)

VisualStudio2010のデザイナでは、レイアウトのリセットというメニューが追加されています。

レイアウトのリセット

それぞれ、XAMLから下記プロパティに関する記述が削除されます。

サイズ Height,Width
配置 VerticalAlignment,HorizontalAlignment
余白 Margin

結構便利でした。

2010年5月20日木曜日

WPFとWinForm

@ITにて、WPFの連載とWinFormの連載がほぼ同時にスタート。

連載:Windowsフォーム開発入門【Visual Studio 2010対応】
http://www.atmarkit.co.jp/fdotnet/chushin/introwinform_index/index.html
連載:WPF入門
http://www.atmarkit.co.jp/fdotnet/chushin/introwpf_index/index.html

いよいよ全面対決か?
何度も途中で挫折しているので、WPFもう一回最初っから勉強し直そうかな。

2010年5月18日火曜日

Visual Studio 2010 で WPF

VS2010では、WPFのデザイナが強化されています。便利。
でも、VS2010で作成したプロジェクトはBlend3で開けません。残念。

Blend4待ち?

2010年5月1日土曜日

x64環境のOLEDBドライバ

長らくx64環境からMDBファイルにアクセスすることが出来なかった。
(正しくは、32bitアプリとしてWOW64上で動作する様に、ビルド構成としてx86を指定する必要があった。)

Office2010(x64)をインストールすることにより、64bitのアプリケーションでもMDBファイルにアクセスできるようになる。ConnectionStringで”Microsoft.ACE.OLEDB.12.0”するだけである。

データ接続コンポーネントも、今はベータがとれていないが、そのうちベータがとれるだろう。
(2010 Office system Beta ドライバ: データ接続コンポーネント)
http://www.microsoft.com/downloads/details.aspx?familyid=C06B8369-60DD-4B64-A44B-84B371EDE16D&displaylang=ja

これにより、32bitでは"Microsoft.JET.OLEDB.4.0"、64bitでは"Microsoft.ACE.OLEDB.12.0”と接続文字列を切り替えることにより、どちらの環境でも動作させることが可能になる。
※32bitでも下記ドライバをインストールすれば、"Microsoft.ACE.OLEDB.12.0”で接続が可能。
2007 Office system ドライバ: データ接続コンポーネント
http://www.microsoft.com/downloads/details.aspx?FamilyId=7554F536-8C28-4598-9B72-EF94E038C891&displaylang=ja

なお、32bitで動作しているか64bitで動作しているかは、IntPtr.Sizeで判定が可能だそうだ。

(とあるコンサルタントのつぶやき:Part 2. .NET Framework 2.0 アプリケーションの 64 ビット対応)
http://blogs.msdn.com/nakama/archive/2008/11/06/part-2-net-framework-2-0-64.aspx

なお、アプリケーションの内部から、現在自分が 64 ビット/32 ビットどちらで動作しているのかを知る一番簡単な方法は、IntPtr.Size プロパティをチェックするというものです。

  • IntPtr.Size = 8 の場合は 64 ビットモードでプロセスが動作している。
  • IntPtr.Size = 4 の場合は 32 ビットモードでプロセスが動作している。

2010年4月24日土曜日

アンインストール

訳あって、VisualStudioをアンインストール中。
何でこんなに面倒なんでしょう。

インストールされていたのは、VS2005/2008/2010+SQLServer2005/2008。
でもプログラムの追加と削除にはかなりの数(50ぐらい?)の関連すると思われるプログラムが…
もちろんこれらはVSをアンインストールするだけでは残ったまま。

何でこんなに面倒なんでしょう。

2010年4月22日木曜日

Visual Studio 2010

日本語版をインストール。 週末に試そう。

2010年4月20日火曜日

Windows7 on viliv S5

というわけで、Windows7化完了です。

感想。
・手書きツールいい感じ
・gpsとCubeIUが不調
・動作はもっさり

無題 
最後にUXインデックスでした。

2010年4月16日金曜日

viliv S5 、Windows7化

週末を利用して、viliv S5にWindows7をインストールすることを画策中。

とりあえず、ブータブルのUSBメモリを作成中。
最近はMicrosoftがISOからブータブルUSBメモリを作成するツールを配布してるんですな。
ISOのダウンロード販売といい、便利な時代になったもんだ。
http://www.microsoftstore.jp/Form/Guide/downloadTool.aspx

2010年4月14日水曜日

PLinq

Visual Studio 2010(.NET Framework 4)より、PLINQ (Parallel LINQ)が追加され、並列処理が簡単にできるようになっています。

10 行でズバリ !! 並列プログラミング - PLINQ (C#)より
PLINQ は LINQ によるデータ コレクションに対するクエリ処理を並列化するためのものであり、PLINQ を使用することで LINQ クエリの Select 句や Where 句で実行されるロジックを容易に並列処理化することが可能です。PLINQ の機能は ParallelEnumerable クラス (System.Linq.ParallelEnumerable) の拡張メソッドとして提供されており、LINQ クエリの処理対象データ コレクションに対して ParallelEnumerable クラスの拡張メソッドの呼び出しを追加するだけでデータ コレクションへの処理を並列化し、マルチプロセッサー/マルチコア CPU の処理能力を活用して処理時間を短縮することができます。

と言うわけで、先日の重いLinq構文を何とか出来ないかとあちこちにAsParallelを追加してみました。
が、Aggregate構文を途中で使用しているためか、追加前より速くなることはありませんでした。
残念。

Visual Studio 2010

というわけで、早速お試し。

気になる機能その1 Coded UI Test
なんと、GUIのUnitテストが出来るらしい。

①まずは、超簡単なWinFormアプリを作成
image
テキストボックスに文字列をいれて、ボタンを押下すると下記ダイアログを表示する
image
ただそれだけです。

②テストの追加
image 
Testメニューから、NewTestを選択。そうすると下記ダイアログが表示されるので、Coded UI Testを選択する。
 
 image
そうすると、どうやってUIテストを作成するかを聞いてくる。一番最初はテスト資産がないので、上を選択。

image
 
画面の右下に、小さなポップアップ?が表示されるので、準備OK。

ここからの正しい使い方がよくわかっていないので、適当に。
(i)テスト対象アプリの起動
とりあえず、テスト対象が起動していないことにはどうにもならないので、起動します。
(ii)赤いボタンを押下
操作記録が開始されます。
(iii)適当に操作
検証したいポイントの手前まで操作します。今回の場合、はテキストボックスに文字入力&ボタン押下。
(iv)一番右のボタン押下
行った操作に対するコードが生成されます。
(iv)照準アイコンを検証したいコントロールへD&D
対象コントロールのプロパティーが表示されます。
image 
(v)検証したいプロパティーを選択し、Add Assertionをクリック
image 
表示されるダイアログで、検証の条件を追加します。
(vi)再び、コードを生成
今度はAssertionコードが追加されます。

以上で、テストケースの作成は終わり。

③テストの実行

[TestMethod]
public void CodedUITestMethod1()
{
this.UIMap.RecordedMethod1();
this.UIMap.AssertMethod1();
}

上記テストメソッドが作成されるので、右クリックからテストの実行を選択。
/>テストが実行される。
※テスト実行前にも必ずテスト対象を起動してあげないとダメ。このあたりはちゃんとした手法があると思うのだがよくわからん。

気付き
IMEが有効になっていると、途中でテストが失敗する。
いまいち。自動テストとかできるんだろうか。。。

2010年4月13日火曜日

Visual Studio 2010

MSDNサブスクリプションで、ダウンロードが開始されてますな。
英語版だけど。日本語はいつ?

2010年4月11日日曜日

pocket wifi を買った

前々から欲しかったPocket Wifiを買ってしまった。
http://emobile.jp/pocketwifi/

買った後で、何なんですが、コース別の料金を比べてみた。
image

スーパーライトのライト加減がよくわかりますな。
どのコース従量の部分が狭いこと。。。

2010年4月8日木曜日

順列の問題

0~9までの数字のカードがN枚ある。同じ数字のカードは1枚とは限らない。
そこから、M枚使用しM桁の整数を作るとき、小さい方から数えi番目の数値は何か?
※先頭桁に0はこないものとする。

という問題が与えられた場合、これを効率よく説くにはどうすればよいか?

とりあえず、効率よくという部分は無視して、順列を作成して前から数えてみた。順列を作成するに当たりLinqを使用しているサイトが見つかったので、利用にさせていただいた。
http://d.hatena.ne.jp/taguo/20080722/1216745650

class Program
{
static void Main(string[] args)
{
int[] array = {0,0,1,2,2,3};
var result = array.GetPermutation(4)
.Where(x => x.ElementAt(0) != 0)
.Select(x => string.Join("", x.Select(i => i.ToString()).ToArray()))
.Distinct();

result = result.Skip(10).Take(1);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
}

public static class Util
{
public static IEnumerable<IEnumerable<T>> GetPermutation<T>(this IEnumerable<T> source, int count)
{
return Enumerable.Range(0, count)
.Select(_ => source)
.Select(et => et.Select((t, i) => new { t, i }))
.Aggregate(Enumerable.Repeat(Enumerable.Repeat(new { t = default(T), i = default(int) }, 0), 1)
, (ac, et) => from a in ac
from t in et
where !a.Contains(t)
select a.Concat(Enumerable.Repeat(t, 1)))
.Select(ea => ea.Select(a => a.t));
}
}

2010年4月3日土曜日

delegate-非同期呼出

実は、delegateの非同期呼出は使ったことがなかったり…
というわけで、MultiCastDelegateといえどもターゲットが複数あるとダメなのは初めて知りました。
image 
出来ても良さそうなのにね。

2010年4月1日木曜日

delegate-同期呼出

delegateは、メソッド情報(Methodプロパティー)を呼びメソッドの定義されるインスタンスの情報(Targetプロパティー)を持ち、それを同期または非同期に呼び出すことができる。

というわけで、まずは同期呼出から。とっても基本的な使い方。

delegate void Hoge(string str);

static void Main(string[] args)
{
Hoge hoge = null;

hoge = Console.WriteLine;

hoge("AAA");
hoge.Invoke("AAA");
}

9行目と10行目はどちらも同じILがはき出され、この場合、Console.WriteLineが実行される。

delegateで宣言すると、MultiCastDelegateのサブクラスとなるので、常にInvocation Listを作ることが可能。

static void Main(string[] args)
{
Hoge hoge = null;

hoge = Console.WriteLine;
hoge += delegate(string str)
{
Console.WriteLine(str.ToLower());
};

hoge("AAA");
}

メソッドはデリゲートに登録された順番に順次実行されていく。また、+=演算子はDelegate.Combineに置き換えられる。

メソッドの引数は同じオブジェクトが順番に渡されるため、1番目のメソッドで行われた変更を2番目のメソッドへと引き継ぐ。MultiCastDelegateの場合、最後のメソッドの戻り値以外は捨てられるので、引数のオブジェクトを通してしか情報の伝達ができない。

class Program
{
//戻値の型 デリゲートの型名 引数の型
delegate void Hoge(Class c);

static void Main(string[] args)
{
Hoge hoge = null;

hoge += AAA;
hoge += AAA;
hoge += AAA;
hoge += AAA;

hoge(new Class());
}

static void AAA(Class c)
{
Console.WriteLine(c.MyProperty);
++c.MyProperty;
}
}


class Class : Interface
{
public int MyProperty { get; set; }
}

delegate

delegateはC#の言語をもっとも特徴付ける者だと思ってる。
#といってもC#以外はJavaぐらいしか知らないけど…それも1.4

というわけでdelegate再入門

//戻値の型 デリゲートの型名 引数の型
delegate void Hoge(string str);

引数の変数名は余分な気がするが、上記のように宣言することで、MultiCastDelegateを継承した独自型が生成される。

image
上記、delegateの宣言をReflectorで見た様子。
BeginInvokeメソッドの引数と、Invokeメソッドの引数および戻値は、delegateの宣言時の型が使用される。

2010年3月29日月曜日

UIパターン

UIはどうも苦手。勉強しなきゃ何だけどなぁ。
後で読むようにまとめておく。

エンジニアにもわかる「ユーザーインターフェース設計」
http://techblog.yahoo.co.jp/cat207/how_to/post_12/

ソシオメディア:UIデザインパターン
https://www.sociomedia.co.jp/category/uidesignpatterns

インフラジスティックス:Quince
http://jp.quince.infragistics.com/

あと、WPF向けのコントロールとか欲しくなるなぁ。個人では絶対無理だけど。
http://jp.infragistics.com/dotnet/netadvantage/wpf.aspx#Overview
http://www.devcomponents.com/dotnetbar-wpf/
http://www.actiprosoftware.com/Products/DotNet/WPF/WPFStudio/Default.aspx

2010年3月27日土曜日

Interfaceは参照型

Interfaceは参照型だったよな。と思い確認。

class Program
{
static void Main(string[] args)
{

Struct s = new Struct();
s.MyProperty = 1;

Interface i = s;
i.MyProperty = 2;

Interface i2 = i;
i2.MyProperty = 3;

Console.WriteLine("s :{0}", s.MyProperty);
Console.WriteLine("i :{0}", i.MyProperty);
Console.WriteLine("i2:{0}", i2.MyProperty);
}
}

interface Interface
{
int MyProperty { get; set; }
}

struct Struct : Interface
{
public int MyProperty { get; set; }
}
結果
image

正解。

つまり、Interface型に代入する際にボックス化が行われているということ。

class Program
{
static void Main(string[] args)
{
var val = new Struct();
var val2 = new Class();

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000000; i++)
{
object obj = val;
}
Console.WriteLine("struct -> object :" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
Interface obj = val;
}
Console.WriteLine("struct -> Interface:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val;
}
Console.WriteLine("struct -> struct :" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
Interface obj = val2;
}
Console.WriteLine("class -> Interface:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
object obj = val2;
}
Console.WriteLine("class -> object :" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val2;
}
Console.WriteLine("class -> class :" + sw.Elapsed);


}
}

interface Interface
{
int MyProperty { get; set; }
}

struct Struct : Interface
{
public int MyProperty { get; set; }
}


class Class : Interface
{
public int MyProperty { get; set; }
}

image

2010年3月25日木曜日

SQLite

以前のエントリで、Decimal型がDoubleに丸められてDBにInsertされることを書いた。
その後いろいろ調べた結果、フィールド型にNONEを指定していたのが原因だった。フィールド型をNONEで作成すると、NUMERICのaffinityが適用されるらしい。

http://www.sqlite.org/datatype3.html
Datatypes In SQLite Version 3 - 2.1 Determination Of Column Affinity

  1. If the declared type contains the string "INT" then it is assigned INTEGER affinity.
  2. If the declared type of the column contains any of the strings "CHAR", "CLOB", or "TEXT" then that column has TEXT affinity. Notice that the type VARCHAR contains the string "CHAR" and is thus assigned TEXT affinity.
  3. If the declared type for a column contains the string "BLOB" or if no type is specified then the column has affinity NONE.
  4. If the declared type for a column contains any of the strings "REAL", "FLOA", or "DOUB" then the column has REAL affinity.
  5. Otherwise, the affinity is NUMERIC.

つまり、NONEのaffinityを適用されるためには、フィールドをBLOB型もしくは型指定なし(NONEの指定ではない)で作成しなくてはならないようだ。NONE指定すると、その他になり5番のNUMERICが適用されるわけだ。

ちなみに、↓がテーブルを作成する際に使用したSQLiteStudioのテーブル作成画面。
カラム追加のデフォルトデータタイプがNONEになっている。
image

そして、しっかりDDLにNONEと記載される。
image
引っかかった。

その後、データタイプをBlobで作成したところ、文字列として格納されることを確認した。

2010年3月22日月曜日

boxing(ボックス化)

boxing(ボックス化)とは、値型を参照型であるobjectに変換する機能。
これにより、参照型であるobjectに値型を代入することができる。
ただし、パフォーマンス上の注意が必要。Generic型を使用することにより、boxingを防ぐことができる。

static void Main(string[] args)
{
var val = new Struct();
var val2 = new Class();

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000000000; i++)
{
object obj = val;
}
Console.WriteLine("struct -> object:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val;
}
Console.WriteLine("struct -> struct:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
object obj = val2;
}
Console.WriteLine("class -> object:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 1000000000; i++)
{
var obj = val2;
}
Console.WriteLine("class -> class :" + sw.Elapsed);


var list = new List<Struct>(100000000);
var list2 = new List<Class>(100000000);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list.Add(val);
}
Console.WriteLine("generic list <- struct:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list2.Add(val2);
}
Console.WriteLine("generic list <- class :" + sw.Elapsed);

var list3 = new ArrayList(100000000);
var list4 = new ArrayList(100000000);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list3.Add(val);
}
Console.WriteLine("normal list <- struct:" + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
list4.Add(val2);
}
Console.WriteLine("normal list <- class :" + sw.Elapsed);
}

struct Struct
{
public int MyProperty { get; set; }
}

class Class
{
public int MyProperty { get; set; }
}

image
違いは一目瞭然。

2010年3月21日日曜日

値型と参照型

EffectiveC#を読んで、基本に立ち返ってみた。

(参照渡)

class Program
{
static void Main(string[] args)
{
var val = new Class();
var val2 = val; //参照渡し

val.MyProperty = 100;

//100 が表示される
Console.WriteLine(val2.MyProperty);
}
}

class Class
{
public int MyProperty { get; set; }
}

classは参照型であり、代入は参照がコピーされる。なので、 valとVal2の指す実体は同じ。 
image

(値渡)

class Program
{
static void Main(string[] args)
{
var val = new Struct();
var val2 = val; //値渡し

val.MyProperty = 100;

//0 が表示される
Console.WriteLine(val2.MyProperty);

}
}

struct Struct
{
public int MyProperty { get; set; }
}

structは値型であり、代入はコピーが作成されるので、valを変更してもval2に影響はない。
image

2010年3月20日土曜日

本を買った


今更ながら、EffectiveC#。More~は持ってるけど一応。


@ITの記事を見てて、欲しくなりました。


Amazonに勧められました。

2010年3月19日金曜日

FriendFeed

以前のエントリで、RDBにスキーマレスなデータを格納する方法を2種類検討した。

で、2種類の方法をうまくいいとこ取りした製品があるようだ。
http://www.infoq.com/jp/news/2009/04/friendfeed-schemaless-mySQL

検索を行うカラムのみ分解しておけ、ということなのね。

2010年3月18日木曜日

SQLite-型のないカラム

SQLiteはデータ型を指定せずにカラムを作成することがで、様々な型を適切(?)に格納することができる。
これは、オブジェクトをプロパティで分割して格納する際に非常に都合がよい。

というわけで、検証。
DecimalがDoubleとして格納されるために有効桁数が小さくなってしまってるので困りもの。どうにか回避方法はないものか。

static void Main(string[] args)
{
ConnectionStringSettings setting = ConfigurationManager.ConnectionStrings["SQLiteConnection"];
DbProviderFactory factory = DbProviderFactories.GetFactory(setting.ProviderName);

using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = setting.ConnectionString;
connection.Open();
DbCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "Insert into Data Values (?, ?, ?)";
{
DbParameter p1 = factory.CreateParameter();
p1.DbType = DbType.Int32;
insertCommand.Parameters.Add(p1);
DbParameter p2 = factory.CreateParameter();
p2.DbType = DbType.String;
insertCommand.Parameters.Add(p2);
DbParameter p3 = factory.CreateParameter();
p3.DbType = DbType.Object;
insertCommand.Parameters.Add(p3);
}
PropertyInfo[] props = typeof(Data).GetProperties();
var propDic = props.ToDictionary(x => x.Name);
using (DbTransaction tran = connection.BeginTransaction())
{
foreach (var data in GetPersonList().Take(2))
{
insertCommand.Parameters[0].Value = data.IntVal;
foreach (var prop in props)
{
insertCommand.Parameters[1].Value = prop.Name;
insertCommand.Parameters[2].Value = prop.GetValue(data, null);
insertCommand.ExecuteNonQuery();
}
}
tran.Commit();
}

DbCommand selectCommand = connection.CreateCommand();
selectCommand.CommandText = "Select * From Data";
using (DbDataReader reader = selectCommand.ExecuteReader())
{
while (reader.Read())
{
var prop = propDic[reader.GetString(1)];
Console.Write(prop.Name + ":" + reader.GetFieldType(2) + ":");
if (prop.PropertyType == typeof(int))
{
Console.WriteLine(reader.GetInt32(2));
}
else if (prop.PropertyType == typeof(long))
{
Console.WriteLine(reader.GetInt64(2));
}
else if (prop.PropertyType == typeof(string))
{
Console.WriteLine(reader.GetString(2));
}
else if (prop.PropertyType == typeof(bool))
{
Console.WriteLine(reader.GetBoolean(2));
}
else if (prop.PropertyType == typeof(DateTime))
{
Console.WriteLine(reader.GetDateTime(2));
}
else if (prop.PropertyType == typeof(double))
{
Console.WriteLine(reader.GetDouble(2));
}
else if (prop.PropertyType == typeof(decimal))
{
Console.WriteLine(reader.GetDecimal(2));
}
}
}
}
}

static IEnumerable<Data> GetPersonList()
{
int id = 0;
while (true)
{
yield return new Data
{
IntVal = id,
LongVal = long.MaxValue,
Text = Path.GetRandomFileName(),
Flag = id % 2 == 0,
Date = new DateTime(2010, 1, 1).AddDays(id),
DoubleVal = double.MaxValue,
DecimalVal = decimal.MaxValue,
};
id++;
}
}

private class Data
{
public int IntVal { get; set; }
public long LongVal { get; set; }
public string Text { get; set; }
public bool Flag { get; set; }
public DateTime Date { get; set; }
public double DoubleVal { get; set; }
public decimal DecimalVal { get; set; }
}

2010年3月16日火曜日

CSVとSQL

CSVファイルに対してSQLを発行できるらしい。知らんかった。
サンプルはJScript。

var args = WScript.Arguments;
var fullName = args(0);

var fso = new ActiveXObject("Scripting.FileSystemObject");
var path = fso.GetParentFolderName(fullName);
var basename = fso.GetBaseName(fullName);
var filetype = fso.GetExtensionName(fullName);

var con = new ActiveXObject("ADODB.Connection");
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;"
+ "Data Source=" + path + ";"
+ "Extended Properties=\"text;HDR=YES;FMT=Delimited;\";";
con.Open();

// CSVファイルから、SQLでクエリ
var rs = con.Execute("select * from [" + basename + "#" + filetype + "] where sex = '男' order by Age;");
while (!rs.EOF) {
var id = rs.Fields("ID");
var name = rs.Fields("Name");
var age = rs.Fields("Age");
var address = rs.Fields("Address");
WScript.Echo(id + "," + name + "," + age + "," + address);
rs.MoveNext();
}

rs.Close();
con.Close();

読み込んだファイルは以下の通り
ID,Name,Age,Address,Sex
1,佐藤,30,東京,女
2,鈴木,12,北海道,男
3,高橋,35,兵庫,男
4,田中,28,愛媛,女
5,渡辺,14,愛知,女
6,伊藤,22,佐賀,男

2010年3月15日月曜日

SQLクエリ

以前のエントリで、データをプロパティに分解して格納する方法、検索方法がどのように変わるか検討してみた。

通常
<Person>テーブル

ID Name Age Address Sex

Select * From Person Where Age >= 20 And Age <= 29 And Sex='男'

20代男性を検索

分割
<Person>テーブル


IDPropertyNameValue
Select * From Person Where ID in
(Select Id From Person Where PropertyName = 'Age' And Value >= 20 And Value <= 29
Intersect
Select Id From Person Where PropertyName = 'Sex' And Value = '男')

AndはIntersectに、ORはUnionに変換すれば良さそう。でもパフォーマンス大丈夫か?

2010年3月14日日曜日

DbDataSourceEnumerator

DbProviderFactoryから作成できる、DbDataSourceEnumerator。一度も使ったことがなかったので、使ってみた。

if (factory.CanCreateDataSourceEnumerator)
{
DbDataSourceEnumerator dse = factory.CreateDataSourceEnumerator();
dataGridView1.DataSource = dse.GetDataSources();
}
なかなか、CanCreateDataSourceEnumeratorプロパティーがTrueにならない。
どうやら、SQLClient(SQLServer用)でしか使えないっぽい(?)

Commonに必要か?

2010年3月13日土曜日

DbProviderFactory(その2)

前回の続き(?)。
Providerに依存しないコードを書いてみた。


ConnectionStringSettings css = ConfigurationManager.ConnectionStrings["MyConnection"];
DbProviderFactory factory = DbProviderFactories.GetFactory(css.ProviderName);

DbConnectionStringBuilder sb = factory.CreateConnectionStringBuilder();
sb.ConnectionString = css.ConnectionString;
//この辺はProviderに依存するよなぁ
sb.Add("Password", "xxxx");

using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = sb.ConnectionString;
connection.Open();
//factory.CreateCommand()でもいいけど、こっちの方が素直な気がする。
DbCommand command = connection.CreateCommand();

//ここも依存することが多いよね。
command.CommandText = "SELECT * FROM TABLE1 WHERE ID = ?";
DbParameter p = factory.CreateParameter();
p.DbType = DbType.Int32;
p.Value = 1;
command.Parameters.Add(p);

using (DbDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
reader.GetInt32(0);
}
}
}

DbProviderFactory

DbProviderFactoryを使用することにより、データプロバイダに依存しない実装が可能。で、備忘録

使用可能なProvider一覧を取得
DbProviderFactories.GetFactoryClasses();
machine.configより、DataProviderの情報を取得している。
戻り値はDataTable型なので、DataGridViewを使えば簡単に内容を確認することができる。
image

ApplicationでDataProviderを追加したい場合は、app.configに設定することで追加可能。 例えば、PostgreSQLの場合は、↓の様に設定。

<system.data>
<DbProviderFactories>
<add name="Npgsql Data Provider" invariant="Npgsql" description=".Net Framework Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.8.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
</DbProviderFactories>
</system.data>
そうすることで、DbFactoryが取得可能となる。
image

app.configよりConnectionStringを取得してDbProviderFactoryを作成 

ConnectionStringSettings css = ConfigurationManager.ConnectionStrings["MyConnection"];
DbProviderFactory factory = DbProviderFactories.GetFactory(css.ProviderName);
ConfigurationManagerからConnectionStringSettingsを取得。(System.Configuration.dllの参照が必要)
ConnectionStringSettingsよりProviderNameを取得し、DbProviderを作成

あとは、factory.CreateXXXXX()で作成し放題!

2010年3月11日木曜日

SQLite

というわけで(?)、ファイルDBのSQLiteを評価中。

とりあえずパフォーマンス比較をやってみた

DB

Insert

Update

Delete

Select

MDB

21.32

32.07

27.18

46.05

SQLServer CE

3.53

4.90

4.05

9.59

SQLite

0.89

1.05

0.85

1.07

※処理
Insert×10万回
Update×10万回(主キーを条件に1レコード更新)
Select×10万回(主キーを条件に1レコード取得)
Delete×10万回(主キーを条件に1レコード削除)
テーブルは、2カラム(主キー、値)のみ。

※環境

OS WIndows7 Ultimate(x64)
CPU Core-i7 920
Memory 12G

SQLiteはえー。

2010年3月10日水曜日

スキーマレス

RDBにスキーマレスなデータを格納する方法を検討中

スキーマレスといえばXMLDBという気もするが、インストール不要のお手軽ファイルDBがよいので、やっぱりRDBになってしまう。格納方法として思いついたのが以下の2通り。

  • シリアライズ

オブジェクトをシリアライズしてそのままBlob型のカラムに格納する方法

ID Data
1 <?xml version="1.0"?>
<名前 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<姓>山田</姓> <名>太郎</名>
</名前>
2 <?xml version="1.0"?>
<名前 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<姓>山田</姓> <名>次郎</名>
</名前>

プログラム側はC#なので、オブジェクトをXMLSerializerに突っ込んでDBに保存・読込を行えばよいので実装が楽そう。問題はどうやって検索するのか?

  • プロパティーに分解

オブジェクトのプロパティー単位でレコードを追加する方法

ID PropertyName Value Type
1 山田 System.String
1 太郎 System.String
2 山田 System.String
2. 次郎 System.String

こちらは検索はできそう。でもレコード数が多くなるので、Insertが大変そう。