11

私は 4 層の ASP.Net Web アプリケーションを構築しています。レイヤーは次のとおりです。

  1. データレイヤー
  2. エンティティ層
  3. ビジネスレイヤー
  4. UIレイヤー

エンティティ レイヤーにはデータ モデル クラスがあり、T4 テンプレート (POCO) を使用してデータレイヤーのエンティティ データ モデル (edmx ファイル) から構築されます。エンティティ レイヤーは、他のすべてのレイヤーで参照されます。

私のデータレイヤーには、次のような機能を持つ SourceKeyRepository というクラスがあります。

public IEnumerable<SourceKey> Get(SourceKey sk)
{
    using (dmc = new DataModelContainer())
    {
        var query = from SourceKey in dmc.SourceKeys
                    select SourceKey;

        if (sk.sourceKey1 != null)
        {
            query = from SourceKey in query
                    where SourceKey.sourceKey1 == sk.sourceKey1
                    select SourceKey;
        }

        return query;
    }
}

このアプリケーションの他のレイヤーでクエリを実行したくないため、遅延読み込みは無効になっています。UI レイヤーの情報にアクセスしようとすると、次のエラーが表示されます。

ObjectContext インスタンスは破棄されており、接続を必要とする操作には使用できなくなりました。

これは、私の DataModelContainer "dmc" が破棄されたためだと確信しています。この IEnumerable オブジェクトをデータ層から返して、ObjectContext に依存せず、DataModel のみに依存するようにするにはどうすればよいですか?

データ層でのみ遅延読み込みが発生するように制限する方法はありますか?

4

4 に答える 4

18

queryは遅延評価されるため、列挙するまでデータはデータベースから取得されません。

もしあなたがそうするなら:

return query.ToList();

クエリを強制的に実行し、問題を回避します。

呼び出し元がコレクションを列挙すると、 ObjectContext ( dmc) が句のおかげで既に破棄されているため、エラー メッセージが表示されますusing(これは良いことです。データベース関連のリソースを早期に破棄してください!)。

編集

私が使用した元の投稿では、AsEnumerable()これは正しいと思いました-最近、この正確な状況で自分で使用しようとするまで。AsEnumerable()コンパイル時の型変換のみを行います - 列挙しません。クエリを強制的に列挙するには、Listまたは他のコレクションに保存する必要があります。

于 2010-05-21T17:51:56.300 に答える
5

使用しないでください

return query.AsEnumerable();

使用する

return query.ToArray();

コンテキストを破棄する前に。

AsEnumerableを返すと、オブジェクトが参照されるまでforeachは実行されません。これを配列に変換すると、オブジェクトが破棄される前にforeachが確実に実行されます。次に、コンテキストをusingブロック(実行する必要があること)に配置できます。

于 2011-04-10T06:36:04.913 に答える
5

queryたとえば、オブジェクトでいくつかのメソッドを呼び出すことができます

return query.AsEnumerable();

これにより、クエリを確実に実行できるため、後でオブジェクト コンテキストが必要ないことを確認できます。

于 2010-05-21T17:53:18.633 に答える
2

In my opinion, this scenario has no relevance with AsEnumerable() or AsQueryable(). Try this;

 public IEnumerable<SourceKey> Get(SourceKey sk, DataModelContainer dmc) {    

    var query = from SourceKey in dmc.SourceKeys
                select SourceKey;

    if (sk.sourceKey1 != null)
    {
        query = from SourceKey in query
                where SourceKey.sourceKey1 == sk.sourceKey1
                select SourceKey;
    }

    return query;

}

And you must get this property with

using (dmc = new DataModelContainer()) {
 // GET
}
于 2010-10-26T11:26:25.973 に答える