2

私は現在、EF 4.3 で Table-Per-Type アーキテクチャを使用したモデル ファースト アプローチを採用している EF Fluent プロジェクトに取り組んでいます (そうです、そのように書くのが好きです)。

過去数か月にわたってわかったように、Table-Per-Type と継承はうまく機能しません ->詳細情報。私は 7 つの派生クラスを持つ単一の基本クラスを使用していますが、7 つの派生クラス全体でアイテムを返すだけでは特に高速ではありません。実行タイミングに関しては、EF が 5 つのレコードのリストを取得するのに 5 ~ 7 秒かかり、その後の実行は 2.5 ~ 4 秒程度です。これは受け入れられないと言っても過言ではないので、別の方法を検討しています...

私ができることは、データベースを複数回ヒットすることです。つまり、各タイプのオブジェクトを個別に取得して、単一のコレクションに照合しようとします。ただし、コードはせいぜい扱いにくいです。つまり、

IList<MyBaseClass> items = new List<MyBaseClass>();

dbContext.Database.SqlQuery<MyFirstDerivedClass>("SELECT * FROM MyBaseClass INNER JOIN MyFirstDerivedClass ON...").ToList().ForEach(x => items.Add(x));

... repeat for each derived class...

return items;

しかし、それはうまくいきます!データベースへの最初のヒットには 2 秒かかり、その後のクエリにはわずか 200 ミリ秒しかかかりません。

私の問題は、これがあまり洗練されていない、保守しやすいなどではないことです。dbContext を ObjectContext にキャストし、ストアド プロシージャ ('spGetMyDerivedItems') でこのようなものを実行して、注文されたすべての派生結果セットを返すことをいじっています。 1 db ヒット...

IList<MyBaseClass> items = new List<MyBaseClass>();

ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext;

using (var connection = oContext.Connection as EntityConnection)
{
    EntityCommand command = connection.CreateCommand();
    command.CommandType = CommandType.StoredProcedure;
    command.CommandText = "spGetMyDerivedItems";
    connection.Open();

    using (EntityDataReader reader = command.ExecuteReader())
    {
        oContext.Translate<MyFirstDerivedClass>(reader).ToList().ForEach( x => items.Add(x));
        reader.NextResult();
        ...repeat for each derived type...          
    }
}

return items;

ただし、これは、CommandText が無効であり、「ContainerName」を提供する必要があることを訴える InvalidOperationException では機能しません。ここで推測するに、EDMX ファイルを使用していた場合、この設定項目を設定できます (DefaultContainerName の使用は機能しません)。しかし、私は流暢なアプローチをとっていて、行き詰まりを感じています。

そう...

EF と table-per-type のパフォーマンスの問題を解決するには、どのような方法がありますか? Fluent / Model First アプローチで ObjectContext を介してストアド プロシージャを実行することは可能ですか? 標準の SQLClient.SqlDataReader を実行して ObjectContext に変換できますか?

前もって感謝します...

4

1 に答える 1

1

OK - ObjectContext は System.Data.SqlClient.SqlDataReader から変換できるようです。つまり、dbContext から (直接) 派生させる必要はありません。これがサンプルコードです...

IList<MyBaseClass> items = new List<MyBaseClass>();

ObjectContext oContext = ((IObjectContextAdapter)dbContext).ObjectContext;

using (var sqlConn = new SqlConnection(dbContext.Database.Connection.ConnectionString))
{
    SqlCommand sqlComm = new SqlCommand(){
        Connection = sqlConn,
        CommandText = "spGetMyDerivedItems",
        CommandType = CommandType.StoredProcedure
    };
    sqlConn.Open();

    using (SqlDataReader reader = command.ExecuteReader())
    {
        oContext.Translate<MyFirstDerivedClass>(reader).ToList().ForEach( x => items.Add(x));
        reader.NextResult();
        ...repeat for each derived type...          
    }
}

return items;

明らかに最善の答えは EF がこれを取り上げるということですが、私は今のところ上記に満足しています。EF5 への移行は良い動きのように聞こえますが、さまざまなタイムスケールを考えると、あなたが知っている悪魔よりも優れています :)

助けてくれてありがとう。

于 2013-02-08T10:04:44.447 に答える