1

Entity Framework 5 Database First、VB.net、Linq、SQL Server 2008 R2、および切断されたリポジトリ パターンを利用するアプリケーションがあります。

EF5.x dbContext ジェネレーターを使用して POCO を作成し、T4 テンプレートを変更して、INotifiyPropertyChanged イベントの発生など、さまざまな追加のビットとボブを追加しました。

さまざまなリンク テーブルがあり、データを「わかりやすい」方法で表示する必要があります。

例として、次の 2 つのテーブルがあります。

色:

Colour_ID    |  Colour_Name    | Created_By | Creation_Date | Modified_By |  Modification_Date
----------------------------------------------------------------------------------------------
   1         |     Blue        |     1      |    22-01-13   |     1       |       23-01-13

ユーザー:

User_ID  |  First_Name  | Last_Name  |
--------------------------------------
   1     |    Peter     | Gallagher  |

DataGrid で「フレンドリー データ」を表示するために、データを取り込み、次のようなコードを使用して「フレンドリー エンティティ」を作成しています。

Using CriticalPathDBContext As CriticalPathEntities = ConnectToDatabase()

        Dim query = (From Colour In CriticalPathDBContext.Colours _
                     .Include(Function(x) x.CreationUser) _
                     .Include(Function(x) x.LastUpdateUser).AsNoTracking.ToList
                     Select New FriendlyColours With {.CreatedBy = If(Colour.CreationUserCode Is Nothing, "", Colour.CreationUser.First_Name & " " & Colour.CreationUser.Last_Name),
                                                      .CreationDate = Colour.CreationDate,
                                                      .CreationUserCode = Colour.CreationUserCode,
                                                      .LastUpdateDate = Colour.LastUpdateDate,
                                                      .LastUpdatedBy = If(Colour.LastUpdateUserCode Is Nothing, "", Colour.LastUpdateUser.First_Name & " " & Colour.LastUpdateUser.Last_Name),
                                                      .LastUpdateUserCode = Colour.LastUpdateUserCode,
                                                      .Colour_ID = Colour.Colour_ID,
                                                      .Colour_Name = Colour.Colour_Name}).OrderBy(Function(x) x.Colour_Name)

        Return New ObservableCollection(Of FriendlyColours)(query)

End Using

上記の私の問題は、より複雑な接続されたエンティティの場合、このタイプのクエリは時間がかかりすぎることです。

バディ クラスを使用して関連データを取得することを検討しましたが、切断されたパターンではうまくいきません。

明らかに、切断されている間、遅延読み込みはオプションではありません...

だから、私の質問は...これを行うより良い方法はありますか? より良いために... より速く読んでください!

どんな助けでもありがたく受け取られます!多分私は明らかな何かを見逃しています!

編集...さらに説明するには:

  • すべての製品、およびそのコンポーネントと製品の在庫品目を返すクエリがあります...
  • 返されるコンポーネント リストには 4 種類あり、製品在庫アイテムのリストもあります。
  • コンポーネントと製品ストック アイテムの各セットを取得し、関連するグリッドに結果を入力します。
  • ユーザーは、さまざまなコンポーネントまたは製品在庫アイテムからアイテムを追加、編集、または削除できます。

クエリは(サイズについて申し訳ありません!);

Dim query = (From ProductList In _DBContext.Products _
             .Include(Function(x) x.CreationUser) _
             .Include(Function(x) x.LastUpdateUser) _
             .Include(Function(x) x.Colour) _
             .Include(Function(x) x.License) _
             .Include(Function(x) x.Pack_Size) _
             .Include(Function(x) x.Customer) _
             .Include(Function(x) x.Supplier) _
             .Include(Function(x) x.ProductComponents) _
             .Include(Function(x) x.ProductComponents.Select(Function(y) y.ApprovalType)) _
             .Include(Function(x) x.ProductComponents.Select(Function(y) y.Component)) _
             .Include(Function(x) x.ProductComponents.Select(Function(y) y.Component).Select(Function(z) z.ComponentType)) _
             .Include(Function(x) x.Product_Stock_Item) _
             .Include(Function(x) x.Product_Stock_Item.Select(Function(y) y.Pack_Type)) _
             .Include(Function(x) x.Product_Stock_Item.Select(Function(y) y.Product_Sizing)) _
             .Include(Function(x) x.Product_Stock_Item.Select(Function(y) y.Units_Of_Measure)) _
             .Include(Function(x) x.ProductType) _
             .Include(Function(x) x.ProductClassification) _
             .Include(Function(x) x.ProductType.ProductDepts) _
             .Include(Function(x) x.Season).AsNoTracking().OrderBy(Function(x) x.Product_Code).ToList
             Select New FriendlyProducts With {.Colour_ID = ProductList.Colour_ID,
                                               .Colour_Name = If(ProductList.Colour_ID Is Nothing, "", ProductList.Colour.Colour_Name),
                                               .CreatedBy = If(ProductList.CreationUserCode Is Nothing, "", ProductList.CreationUser.First_Name & " " & ProductList.CreationUser.Last_Name),
                                               .CreationDate = ProductList.CreationDate,
                                               .CreationUserCode = ProductList.CreationUserCode,
                                               .FriendlyCreationUser = ProductList.CreationUser,
                                               .Cust_Product_Desc_24 = ProductList.Cust_Product_Desc_24,
                                               .Cust_Product_Desc_48 = ProductList.Cust_Product_Desc_48,
                                               .Customer_Code = ProductList.Customer_Code,
                                               .Customer_Name = If(ProductList.Customer_Code Is Nothing, "", ProductList.Customer.NAME),
                                               .Description = ProductList.Description,
                                               .DesignNo = ProductList.DesignNo,
                                               .Gender_ID = ProductList.Gender_ID,
                                               .Gender_Name = If(ProductList.Gender_ID Is Nothing, "", ProductList.Gender.Gender_Name),
                                               .LicenseCode = ProductList.LicenseCode,
                                               .License_Name = If(ProductList.LicenseCode Is Nothing, "", ProductList.License.NAME),
                                               .Pack_Size_ID = ProductList.Pack_Size_ID,
                                               .Pack_Size_Name = If(ProductList.Pack_Size_ID Is Nothing, "", ProductList.Pack_Size.Pack_Size_Name),
                                               .PackagingNR = ProductList.PackagingNR,
                                               .ProductClassification_ID = ProductList.ProductClassification_ID,
                                               .Product_Classification_Name = If(ProductList.ProductClassification_ID Is Nothing, "", ProductList.ProductClassification.ProductClassification_Name),
                                               .Product_Code = ProductList.Product_Code,
                                               .Product_Picture_Path = ProductList.Product_Picture_Path,
                                               .ProductComponentsNR = ProductList.ProductComponentsNR,
                                               .ProductType_ID = ProductList.ProductType_ID,
                                               .ProductType_Name = If(ProductList.ProductType_ID Is Nothing, "", ProductList.ProductType.NAME),
                                               .ProductDept_ID = If(ProductList.ProductType Is Nothing, Nothing, ProductList.ProductType.ProductDept),
                                               .ProductDept_Name = If(ProductList.ProductType Is Nothing, "", (If(ProductList.ProductType.ProductDepts Is Nothing, "", ProductList.ProductType.ProductDepts.NAME))),
                                               .SageDescription = ProductList.SageDescription,
                                               .SeasonCode = ProductList.SeasonCode,
                                               .Season_Name = If(ProductList.SeasonCode Is Nothing, "", ProductList.Season.NAME),
                                               .StrikeOffNR = ProductList.StrikeOffNR,
                                               .Supplier_Code = ProductList.Supplier_Code,
                                               .Supplier_Name = If(ProductList.Supplier_Code Is Nothing, "", ProductList.Supplier.NAME),
                                               .TransfersNR = ProductList.TransfersNR,
                                               .Deleted = ProductList.Deleted,
                                               .LastUpdateDate = ProductList.LastUpdateDate,
                                               .LastUpdatedBy = If(ProductList.LastUpdateUserCode Is Nothing, "", ProductList.LastUpdateUser.First_Name & " " & ProductList.LastUpdateUser.Last_Name),
                                               .LastUpdateUserCode = ProductList.LastUpdateUserCode,
                                               .ProductComponents = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Component"), New ObservableCollection(Of FriendlyProductComponents)),
                                               .ProductPackaging = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Packaging"), New ObservableCollection(Of FriendlyProductComponents)),
                                               .ProductStrikeOffs = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Strike Off"), New ObservableCollection(Of FriendlyProductComponents)),
                                               .ProductTransfers = If(ProductList.ProductComponents.Count > 0, GetProductComponentsByPrimaryName(ProductList.ProductComponents, "Transfers"), New ObservableCollection(Of FriendlyProductComponents)),
                                               .ProductStockItems = If(ProductList.Product_Stock_Item.Count > 0, GetProductStockItems(ProductList.Product_Stock_Item), New ObservableCollection(Of FriendlyProductStockItems))
                                               }).Where(Function(x) x.Deleted = False Or x.Deleted Is Nothing)

WhereGetProductComponentsByPrimaryNameは、単純にコンポーネントをタイプでフィルタリングし、Friendly ObservableCollection を返す関数を呼び出します。

したがって、関連する各コンポーネント セットと製品ストック アイテムは ObservableCollection として返され、これを操作できます...

長文すみません!

編集 - 08-03-13:

上記の問題は解決していませんが、クライアントに、すべての結果を取得してから、後でフィルタリングするためにユーザーに依存するべきではないことを納得させることができました。

これにより、フィルタリングがローカルではなくデータベースで実行されるように、フィルタリングルーチンを再調整することにもなりました。これら 2 つの要因は両方とも、以下のクエリが適切な速度で機能するようになったことを意味します。

エンティティを手動で入力しようとしましたが、Linq が生成したクエリよりもはるかに時間がかかりました。

近いうちに、この問題を再検討して、何を学べるか見てみようと思います。でも、とりあえず回避しました!

4

2 に答える 2

1

これと同じクエリを実行するストアド プロシージャを作成し、結果を新しいエンティティ タイプとして返​​すか、可能であれば FriendlyColours として返します。あなたは正しいです、このようにすることは独り占めです。他に何を追加できるかわかりません。

于 2013-03-02T02:10:20.110 に答える
1

そのクエリにより、大量のデータがネットワーク経由で送信されます。おそらく、必要なデータのみを含むエンティティに射影することから始める必要があります。データのニーズによっては、ここでは役に立たないかもしれません。

SQL は通常、単純なクエリを実行するのに非常に高速であるため、各コレクションを個別にロードしてから、コードでエンティティをまとめてスティッチすることができます。これにより、転送されるデータの量が大幅に削減されます。

このように参加するとパフォーマンスが低下する理由を説明するために、簡単な例を示します。

私のテスト データベースには、データがほとんどない 3 つのテーブルがありますが、それでもパターンが表示されるはずです。

最初の個々のクエリ

SELECT *  FROM [OPath-dev].[dbo].[Groups] g

1;Hästhovarna;nzb5x50vibb;0;NULL;NULL;0

1 行。notepad++によると39文字

SELECT * FROM [OPath-dev].[dbo].[GroupMemberships]

1;1;1
2;1;0

2 行。12文字

SELECT * FROM [OPath-dev].[dbo].[Blogs] where id > 5

フィールドを含む 3 行。

  • 題名;
  • イントロ;
  • 体;
  • 公開日;
  • 作成した;
  • CreatorIP;
  • 作成者;
  • 編集済み;
  • 編集者;
  • EditorIP

5907文字で

2 つの単純なテーブルの結合

  SELECT *
  FROM [OPath-dev].[dbo].[Groups] g
  JOIN [OPath-dev].[dbo].[GroupMemberships] gm on gm.GroupId = g.Id

1;Hästhovarna;nzb5x50vibb;0;NULL;NULL;0;1;1;1
1;Hästhovarna;nzb5x50vibb;0;NULL;NULL;0;2;1;0

長さは 96 文字になりました。これら 2 つを別々のクエリで実行すると、39 + 12 = 51 になります (違いが小さいため、おそらくこれの方が高速です)。

3 つのテーブルすべてを結合する

SELECT *
  FROM [OPath-dev].[dbo].[Groups] g
  JOIN [OPath-dev].[dbo].[GroupMemberships] gm on gm.GroupId = g.Id
  JOIN [OPath-dev].[dbo].[Blogs] b on b.Id > 5

応答は、次の列を含む 6 行です。

  • ID;
  • 名前;
  • JoinCode;
  • 競争クラブです。
  • SourceSystemKey_SystemKey;
  • SourceSystemKey_EntityId;
  • SourceSystemKey_HasValue;
  • ユーザーID;
  • グループ ID;
  • 管理者です
  • ID;
  • 題名;
  • イントロ;
  • 体;
  • 公開日;
  • 作成した;
  • CreatorIP;
  • 作成者;
  • 編集済み;
  • 編集者;
  • EditorIP

現在、応答の長さは 11954 文字であり、突然結合にかなりの代償を払っています。特に、データベースが同じマシン上または非常に高速なネットワーク上にある場合。

これは悪い例ですらあります。私の他のコンピューターではさらに悪い成長を示すより良いデータセットがあります。そして、大量のデータが転送されることになる、さらに多くの列に参加していることを思い出してください。それが Windows アプリケーションであり、WAN 経由でデータベースに接続している場合、これは深刻な問題になりますが、ローカル マシンでもプロファイルを作成すると転送が無料ではないことがわかります。

于 2013-03-02T06:31:00.533 に答える