私は新しい開発プロジェクトのセットアップの初期段階にあり、データベースアクセス戦略をどのように設定するのかは不明です。 Visual Studio 2012を使用し、.NET 4.5とSQL Server 2008または2012をターゲットにします。Entity Framework、DapperとSSDTの組み合わせですか?
私は確信しているのは、Entity Frameworkを使用するかどうか、使用する場合はどの程度かについてです。データベースからデータを読み取り、それを処理することがこのアプリケーションの主な仕事になると、クエリのパフォーマンスが重要になります。私は、EF5がその点でEF4.xよりもずっと優れていることを知っていますが、それは私が最も心配している固有のEFオーバーヘッドではありません(Dapperのようなものはまだ少なくとも2倍速いですが)なぜなら、あまりにも多くのクエリを実行するのは、LINQを使用すると非常に簡単だからです。ですから、純粋なSQLクエリをデータを取得する主な方法にしたいと思います。
しかし、私がEFについて最も逃してしまうことである。
- コンパイル時クエリチェック。
- 変更追跡。
- コードの最初の開発。
- 作業パターンの単位。
私は変更追跡なしで暮らすことができますが、新しいものや更新されたものを特定することは通常困難ではありません。
私が望むのは、このプロジェクトの開発者はテーブルデザイナーを悩ます必要はありませんが、単にPOCOを書くことができるということです。ですから、私はEFのコードの最初のアプローチに本当に感謝しています。これにより、開発者はソースコードを複製し、update-database
と呼び出して、動作するローカルデータベースを持つことができます。これは過去に私にとってうまくいったものです。
私にとって非常に重要なもう一つのことは、作業パターンの単位、または挿入と更新のアトミック性です。私はすべての変更をキューに入れて、SaveChanges
と呼ぶ単一のポイントを持っています。 DapperExtensions
のようなライブラリでは、Insert
メソッドを取得しますが、すぐにデータベース呼び出しを行います。トランザクションをラップしてアトミックにすることはできますが、それはキューに入れることと同じではありません。だから、私はこれのために何らかの並べ替えのメカニズムを自分でロールバックしなければならないだろう。
コンパイル時のクエリチェックでは、SQL Serverデータツール(SSDT)の使用を検討します。クエリはストアドプロシージャ(C#コードで大規模なクエリ文字列ブロブを避けるため)とSSDTを使用して、ビルド時にチェックすることができます。 SSDTのもう1つの利点は、Visual Studioからターゲットデータベースにストアドプロシージャを展開できることです。そして、最も重要なのは、これらのためのSQLスクリプトはソース管理に存在するということです。
は、だからと、私の解決策は、基本的に3つのデータアクセステクノロジで構成されます:Entity Frameworkの
- をPOCOのdatamodelsからデータベースを作成するための責任を負うことになります。
- 作業パターンを使用してデータを挿入/更新するために使用されます。 1つ目の注意点は、最初に
Attach
エンティティにSQLをコンテキストにフェッチする必要があるということです。
SSDT
- は、コンパイル時にSQLスクリプトを確認するために使用されるだろう。
- スクリプトをGitに保存できます。
- EFがデータベースに展開できないものを展開します。
Dapperの/他のマイクロORMデータ
私は助けるが、これは私が様々な使用フランケンシュタインソリューションのビットで感じることができないをフェッチするために使用される
- ビットとすべての断片。私はまた、SSDTとEFがうまく連携しているかどうかはまだ分かっていません。この簡単な例はうまくいくようです:
// Combo of Dapper, EF and a stored proc that was published through SSDT static void Main(string[] args) { var connectionString = ConfigurationManager .ConnectionStrings["DbDataContext"].ConnectionString; using (var conn = new SqlConnection(connectionString)) using (var ctx = new DbDataContext()) { conn.Open(); var product = conn.Query<Product>("GetProduct", commandType: CommandType.StoredProcedure).First(); ctx.Products.Attach(product); var order = new Order { Product = product }; ctx.Orders.Add(order); ctx.SaveChanges(); } }
このアプローチはうまくいくようですが、面倒です。しかしSSDTをあきらめると、SQLのコンパイル時間チェックができなくなるでしょう。もしEntity Frameworkをあきらめたら、コードに先立ち、簡単に挿入することができなくなります。パフォーマンスの大きな塊でアウト。
私が見逃している選択肢はありますか?そうでない場合は、ここで最善のアプローチは何ですか?
「怠け者があなたを開発者として与えます」 - あなたの仕事は怠惰ではありません。 EFはパフォーマンスのためのエンジニアリングを完璧に提供します。 – millimoose
はい、LINQを使用していません。未処理のSQLに移行する必要がありますが、それでもADO.NET/Dapper(http://goo.gl/ctD9f)の半分のスピードです。 Dapperを使ってクエリを実行することもできます。しかし、私はSSDTをコードから外すためにC#コードのクエリで文字列の大きな匿名の塊を避けたいと考えています。 – JulianR
これは、開発者のコントロールの範囲外にあるフレームワークオーバーヘッドの問題です。私の指摘は、単に「怠惰を助ける」ことは、技術を選択するか選択しないかの良い理由ではないということでした。 ORMの「深さ」のオーバーヘッドを切り捨てようとするなら、N + 1の選択問題によって引き起こされるパフォーマンス上の問題を避けることができます。 (この問題はパフォーマンスにも大きな影響を与えますが、生のSQLで遭遇するのと同じくらい簡単ですし、大規模なuberqueryを書くのはSQLではLINQより難しいので解決するのはずっと困難です) – millimoose