2012年12月7日

Nexus7を買って4ヶ月後の感想 - じわじわと良くなって来た感じ


8月の初めにNexus7を購入してから4ヶ月が経った。

当初は期待半分、「本当に使えるのかなー」という疑い半分、という感じで、まあ少なくともアプリ開発のデバッグ用途には役に立つかなという程度に思っていた。

ところが、時間の経過とともに当初想定していなかった使い方もする様になって来て、だんだんと手放せなくなりつつある。

他の人の感想を読んだりして、「やっぱりNexus7いいね」と改めて見直したり。
Nexus7購入から1ヶ月後 — 乱れなよ、そして召されなよ

Nexus 7が、とりわけヒジョーにかなりイイ
なんと言っても7インチというサイズと軽さが素晴らしい。これはまあ当然として、その他に次のような点が大きいかなと思う。


Googleのサービスと親和性が高い


一番大きいと思うのはChromeの同期機能。これは使い出すと本当に欠かせない。
もちろんGmailも使いやすい。Google Mapの高機能さもやはりAndroidならでは。



Android OSのアップデートがすぐに反映される


購入してから4ヶ月で既に3回のアップデートが配信されている。アップデートのたびに細かい点が改善されているのが嬉しい。

特にAndroid 4.2で追加されたマルチユーザー機能はとても便利。子供に渡す時にさっとユーザーを切り替えて渡すだけで良くなったので本当に助かる。


あと、買った当初は想定していなかった使い方というのは、電子書籍を読む事と動画や音楽を楽しむ事の2つだった。



紙のメモを使わなくなった


Nexus7を買ってからミーティングのメモは全て「7notes with mazec」を使って取る様にしている。

最初の頃は「書き流し入力」をして後からきれいにテキストに変換していたけれども、この頃は手書き文字のままPDFで保存する様にしている。どうしてもテキストに変換する必要があるドキュメントでない限りはこれで十分だ。

最近スタイラスペンが少しヘタって来た様な気がするのでそろそろ買い換えたほうが良いかも知れない。

手書き入力をしない時は、Google日本語入力のGodanキーボードが便利。mazecと状況に応じて使い分けている。



電子書籍が読みやすい


Amazon.co.jpで日本語の電子書籍が買える様になった。Nexus7の話からは外れるけれど、僕にとってはこれは大きかった。

電子書籍が便利なのはわかっているけど「読む本が無いから結局読書には使わないだろうなあ」と思っていた。

でも、Amazonで簡単に日本語の本が探せて、しかも今まで払っていた高い海外向け送料無しで読めるとなると話は全く別だ。

試しに好きな作家の小説を買ってみたら、もちろんNexus7で全く問題なく読めた。7インチの画面はさすがに携帯の画面より読み易い。読んでいる位置やブックマークを携帯やPCのKindleアプリと同期する事も出来るし、やっぱり便利。

検索しても出てこない本がまだまだ多いけれど、早く紙の本と同じものが買えるようになって欲しい。そうしたらNexus7の出番がもっともっと増えると思う。



Youtube動画を連続再生


日常生活の中で、「Youtubeのあの動画を再生しながらこれをしたいな~」という場面が結構ある。

僕の場合は実は「食後の食器洗い」の時間がそれに当たる。手が濡れているので出来れば画面を触らずに自動でどんどん再生してくれると嬉しい。

それを実現してくれるのが「PVSTAR+」というアプリ。これで気に入った動画をずっと流しながら両手で作業が出来る。



音楽を聴きながら寝る


前からSky.FMは聴いていて、「Solo Piano」というチャンネルが僕のお気に入りになっている。

Sky.FM Radio

このアプリが便利なのはスリープタイマー機能が付いているので聴きながら寝入ってしまっても時間が来れば停止してくれる事。きれいなピアノの音を聴きながら眠ると本当に気持ちがいい。

ただ、無料で使っていると、たまに寝かかっている時にコマーシャルが始まって目が覚めてしまう事がある。なので有料アカウントにしようかと真剣に検討中。



結論


そんなこんなで4ヶ月後の感想としては、「Nexus7買って良かった。悔いはない!」と思っている。



 

2012年12月6日

ASP.NET MVCでDbContextのトランザクションと独自SQL 処理のトランザクションを同一のスコープにする

最近毎日 ASP.NET MVC4 でWebアプリケーションを作っている。

今まで独自のO/Rマッパを使っていたので Entity Framework を使い出したのは実はごく最近。

これでSQLを書かなくてもデータの取得や更新が簡単に出来る様になったのは嬉しいのだけれど、当然ストアドプロシージャを呼んだり自分で書いたSQL文を実行したりしたいという場面も結構ある。

そこでいくつかのDBアクセスのパターンを試していて、独自SQLの実行とDbContext経由でのデータ更新を同一のトランザクション内で行いたい、という場合にちょっと困ったので対処方法をメモしておきたい。



とりあえず問題ない例

上の例では別のContextを使っているのでこれはエラーにはならない。 ただしこれだと1つめの更新処理と2つめの更新処理を同一のトランザクション内で実行出来ない。



問題になる例

上の例の様にDbContextからの更新処理をADO.NETのTransaction内に入れた場合は次のようなエラーが起きる。





対処の方法


1. 生成済みのDbConnectionを渡してDbContextを生成する。

DbContextのインスタンスを生成する時に、コンストラクタに既存のDbConnectionを渡すとDbContextで勝手にCloseされる事が無くなる。

これをするためには、DbContextのクラスにDbConnectionパラメータを受け取るコンストラクタを追加する必要がある。



    public class MyEntities : DbContext {

        public MyEntities()
            : base("DefaultConnection") {
        }

        public MyEntities(DbConnection existingConnection)  
            : base (existingConnection, false){ 
        }

        public DbSet<Product> Products { get; set; }
    }


2. EntityConnectionを使ってコネクションをOpenする。

DbContextのDatabase.Connectionは素のSqlConnectionを返す。ただしこれを自分で直接OpenしてしまうとEFの管理情報と一致しなくなる。

DbContextをIObjectContextAdapter型にキャストしてそこからObjectContextを取得し、そのConnectionプロパティ(実態はEntityConnection)に対してOpenを実行すればEFの管理内で処理される。


3. EntityConnectionに対してBeginTransationする。

1、2の後、EntityConnectionに対してBeginTransationしてトランザクションを開始すれば、独自のSQL処理とDbContextのSaveChangesメソッドによる内部的なトランザクションとが同一のスコープで実行可能になる。


対処後の例



動作確認可能な全ソースを含んだサンプルプロジェクトはこちら


参考にしたURL

This SqlTransaction has completed; it is no longer usable. Entity Framework Code First - Stack Overflow

task parallel library - Entity Framework, SqlCommand and TransactionScope - Stack Overflow

Exception from DbContext API: EntityConnection can only be constructed with a closed DbConnection - Diego Vega - Site Home - MSDN Blogs

EntityConnection can only be constructed with a closed DbConnection

2011 7月 « Do Design Space

.net - Frequent saves with entity framework - Stack Overflow

entity framework - EF Code First DBContext and Transactions - Stack Overflow






 

2012年12月4日

ASP.NETのWCFサービスでDbContextから取得したオブジェクトを返そうとするとエラーになる場合の対策

先日、ASP.NETのWCFサービスでEntityFrameworkのDbContext経由で取得したモデルクラスのオブジェクトを返そうとして、壁にぶつかった。

発生したエラーの内容はこんな感じ。
Test method ServiceTest.CustLoadData threw exception:
System.ServiceModel.CommunicationException:
An error occurred while receiving the HTTP response to http://localhost:60741/MyService.svc.
This could be due to the service endpoint binding not using the HTTP protocol.
This could also be due to an HTTP request context being aborted
by the server (possibly due to the service shutting down).
See server logs for more details.
---> System.Net.WebException: The underlying connection was closed:
An unexpected error occurred on a receive.
---> System.IO.IOException:
Unable to read data from the transport connection:
An existing connection was forcibly closed by the remote host.
上記のエラーはWCFサービスの呼び出し側で表示されるエラーなので実際に起こっているエラーの原因はちょっと違う部分にある。


いろいろデバッグに苦労したけれど、とりあえずどうやらWCFサービス内でオブジェクトを返すためにシリアライズしようとしている所でエラーが起きているらしい、という事が分かった。

原因は、DbContextの動作原理としてPOCOに対する変更追跡と遅延ローディングを実現するために内部的に「動的プロキシクラス」というものを生成している事にあるらしい。

動的に生成されたプロキシクラスはシリアライズ対象に出来る「既知のクラス」として認識されないのでエラーになってしまう様だ。

POCO エンティティの使用 (Entity Framework)
『Windows Communication Foundation (WCF) では、プロキシを直接、シリアル化または逆シリアル化できません。その理由は、DataContractSerializer では既知の型のみのシリアル化または逆シリアル化ができますが、プロキシ型は既知の型ではないためです。』

結局対策としては

this.Configuration.ProxyCreationEnabled = false;

の1行をDbContextクラスのコンストラクタ内に入れる事で解決した。
これでデータ取得時に動的プロキシが作成されずに純粋なPOCOが返って来るので、シリアライズ時に問題が発生しなくなる。


ちなみにMSDN内の下のページには「シリアル化中にProxyDataContractResolver クラスを使用してプロキシ型を POCO 型にマップ」する方法が載っている。でもちょっと試してみたところ上手く行かなかったので今回はパスした。
チュートリアル: WCF による POCO プロキシのシリアル化 (Entity Framework)


他の解決策として、動的プロキシの作成を抑止せずにWCFサービスでオブジェクトを返す前に手動でPOCOにデータを詰め替えるという方法もある。

データを詰め替えるのはAutomapperなどのライブラリを使えば簡単に出来るので、ProxyCreationEnabled を falseにするという解決策を取りたくない場合はそちらでも良いかも知れない。



その他参考になりそうなURL:

Entity Framework 4, WCF & Lazy Loading Tip | .NET Zone


Entity Framework v4 POCO templates: repository returns object of incorrect type - Stack Overflow