0

VS2010でEF3.5を使用しています。構造体を返すメソッドがあります。構造体にはオブジェクトarmatuurがあります。構造体が返されたときに、armatuurインスタンスから関連オブジェクトにアクセスしたいと思います。

でも

構造体を返すメソッド:

public LampPostDetail getLamppostInfo(int id)
{
    LampPostDetail lpd;

    lpd.xPos = 0;
    lpd.ypos = 0;
    lpd.armatuur = new Armatuur();

    //get the info from object
    using (var db = new OvisionDBEntities())
    {
        var objects = from o in db.Objects
                      where o.ObjectId == id
                      select o;

        foreach (OVSL.Data.Object o in objects)
        {
            lpd.xPos = o.XCoordinatie;
            lpd.ypos = o.YCoordinatie;
            lpd.armatuur = o.Armatuur; //which is a table in my db
        }

        return lpd;
    }
}

構造体:

public struct LampPostDetail
{
    #region [ Data Members (14)]
    //lamppost info
    public double? xPos;
    public double? ypos;

    //a lamppost can have several armaturen
    public OVSL.Data.Armatuur armatuur; //is a table in my db

    #endregion [ Data Members ]
}

私のクライアントでこれを行うとき:

 LampPostDetail lpd = client.getLamppostInfo(id);
 string brand = lpd.armatuur.producer.name; //producer is related object of armatuur

ObjectDisposedExceptionが発生します。これは、usingブロックが終了した後にLampPostDetailオブジェクトが破棄されるために発生することを理解しています。しかし、どうすればこれを機能させることができますか?クライアントに返す前に必要なすべての情報(ブランド名など)を取得することはできません。

4

2 に答える 2

0

破棄されるのはLampPostDetailではなく、データベースから取得したArmatuurオブジェクト、またはArmatuurが参照しているオブジェクトです。

これを回避するための2つのオプションがあります。1つ目は、エンティティコンテキストをgetLamppostInfoinfoメソッドのオプションのパラメーターにすることです。3.5を使用しているため、元の機能を維持するためにオーバーロードを実行する必要があります。

public LampPostDetail getLamppostInfo(int id,OvisionDBEntities context)
{
...
    try
    {
       OvisionDBEntities db;
       if (context == null)
          db = new OvisionDBEntities();
       else
          db = context;
    ...
    }
    finally
    {
       if (context == null && db != null)
         db.Dispose() // or close maybe
    }

    retun lpd;

 }

 // Overloaded function to keep orignal functionality (C# 3.5 does not have 
 // optional parameters)
 public LampPostDetail getLamppostInfo(int id)
 {
     return LampPostDetail(id,null)
 }

今、あなたはそれを次のように呼ぶことができます:

using (var db = new OvisionDBEntities())
{
   LampPostDetail lpd = client.getLamppostInfo(id,db);
   string brand = lpd.armatuur.producer.name;
}    

また、オブジェクトを参照しようとしても、オブジェクトは引き続き存在します。

もう1つのオプションは、参照されているオブジェクトを破棄する前に、エンティティコンテキストから切り離すことです。

  db.Detach(o.Armatuur); 

ただし、そのオブジェクトによるオブジェクト参照を切り離すとは思いません。したがって、参照ツリーを相互作用させ、オブジェクトも切り離す必要があります。

于 2012-11-05T17:56:45.927 に答える
0

ここで破棄されるのはOvisionDBEntitiesコンテキストだけです。その後、遅延読み込みはできなくなります。どのように対処するのですか?実際、あなたの質問は、いつでもユーザーアクションに必要となる可能性のあるすべてのデータをクライアントに提供するために何ができるかということです。3つまたは4つのオプションがあります。

  1. コンテキストの破棄後にエンティティのナビゲーションプロパティへのアクセスを有効にする標準的な方法は、インクルードを呼び出すことですfrom o in db.Objects.Include("Armatuur.Producer")...。しかし、それは明らかにオプションではありません。

  2. コンテキストをライブにし、遅延読み込みに依存してオンデマンドでデータをフェッチします。これはあなたのためのオプションかもしれません。ただし、長期間有効なコンテキストでは、内部変更の実績が増えるにつれてパフォーマンスが徐々に低下したり、キャッシュされたデータが古くなってリフレッシュ/リロードステートメントがいたるところに散らばったりするなどの問題が発生する可能性があります。

  3. ナビゲーションプロパティ/遅延読み込みの代わりに、呼び出しごとにコンテキストインスタンスを使用するサービス/リポジトリレイヤーからオンデマンドでデータをフェッチします。このオプションはあなたにとってうまくいくと思います。

  4. 技術的なオプションよりも機能的です。少ないデータで実行できるユースケースを設計します(Include結局のところ、それで十分かもしれません)。数千行と数十列のグリッドを取り込むことはできません。適切に設計されたユーザーインタラクションにより、クライアントに送り込まれるデータの量を大幅に減らすことができます(そして、私はこれを取得し始めたばかりです)。

于 2012-11-05T23:56:42.927 に答える