2016-05-13 15 views
2

私はActionが私に返すエラーと混同します。JsonへのEntity Frameworkモデル

public class AddressesManager 
    { 

    private SiteDBEntities entityContext; 

    public Addresses GetAddress(short id) 
      { 
       entityContext = new SiteDBEntities(); 
       var addressList = entityContext.Addresses.Where(a => a.Id == id).FirstOrDefault(); 
       entityContext.Dispose(); 
       return addressList; 
      } 
} 

そして、この関数を呼び出すアクション:

[HttpPost] 
     public ActionResult LoadAddress(short id) 
     { 
      AddressesManager mngr = new AddressesManager(); 
      Addresses address = mngr.GetAddress(id); 
      return new JsonResult() { Data = address }; 
     } 

とjQueryコードウィッヒコールTHITアクション:私は私のマネージャーのコード持って

$.post("/Cart/LoadAddress", { id: id }) 
     .success(function (data) { 

      console.log(data); 
     }) 
    .fail(function (e) { console.log(e) }); 

アクションが実行されているが、しかし、私常にこのエラーコードを500回受け取る:

T ObjectContextインスタンスが破棄されたため、接続が必要な操作には使用できなくなりました。

私は問題を理解できるようにとエンティティ・コンテキストですが、これはなぜ起こりますか?私はすでにDBからデータを実行し、私はもう接続する必要はありません...

EDIT:

THITは私の住所モデルです。それはEFによって自動生成されました:

public partial class Addresses 
    { 
     public int Id { get; set; } 
     public string Title { get; set; } 
     public string State { get; set; } 
     public string Country { get; set; } 
     public string Warehouse { get; set; } 
     public string FirstName { get; set; } 
     public string SecondName { get; set; } 
     public string Phone { get; set; } 
     public short DeliveryType { get; set; } 
     public System.Guid UserId { get; set; } 

     public virtual DeliveryType DeliveryType1 { get; set; } 
     public virtual Users Users { get; set; } 
    } 
+0

アドレス変数のデータを確認しました。すべてOKとデータはここにあります。 – dantey89

+0

アドレスクラスにはいくつかの仮想プロパティがあり、JSONに変換されているので、これらの仮想プロパティも取得する必要があります。 – Kahbazi

+0

はい、そうです。これだよ。では、このエラーを回避する方法は何ですか?マニュアルでモデルをマップしますか? – dantey89

答えて

0

Addressクラスにナビゲーション(子)プロパティがありますか?子プロパティがデフォルトで遅延ロードされるので、DbContextが破棄された後に、この子プロパティにアクセスしようとしているような気がします。

住所コードのコードを投稿できますか?

+0

私のマネージャーのデストラクタでEFcontext.Dispose()を使用して遅延読み込みを回避する良い方法はありますか? – dantey89

0

アドレスクラスの仮想プロパティに属性[JsonIgnore]を追加する必要があると思います。

class Addresses 
{ 
    public int ID { get; set; } 

    [JsonIgnore] 
    public virtual Something Something { get; set; } 
} 
0

アドレスは、あなたのケースでは怠惰にロードする必要があります。したがって、破棄されたデータにアクセスしようとしていて、Entity Frameworkは破棄されたコンテキストを使用しようとしますが、例外が発生します。あなたはMVCでJSONレコードを返却するとき

はたぶん、あなたはあなたがそうあなたのコントローラのようにAllowGetを追加する必要が遅延ロード

var addressList = entityContext.Addresses.Where(a => a.Id == id).FirstOrDefault(); 
entityContext.Addresses.Attach(addressList); 
0

を有効にするために、現在のコンテキストにあなたのアドレスリストを添付する必要があります。

return Json(new { data= address }, JsonRequestBehavior.AllowGet); 

これで適切であるはずです。

1

Addressクラスに2つの仮想プロパティ:DeliveryType1Usersがあるため、エラーが発生します。

addressをJSONに変換すると、その仮想プロパティにアクセスしようとします。ただし、その時点では、あなたのコンテキストはすでに破棄されています。

この問題を回避するには、EF自動生成クラスを直接返さないでください。代わりに、必要なフィールドだけを含むDTOオブジェクト(データ転送オブジェクト)を作成し、それをEFオブジェクトにマップして戻します。たとえば:

public class AddressesDTO 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public string State { get; set; } 
    public string Country { get; set; } 
    public string Warehouse { get; set; } 
    public string FirstName { get; set; } 
    public string SecondName { get; set; } 
    public string Phone { get; set; } 
    public short DeliveryType { get; set; } 
    public System.Guid UserId { get; set; } 
} 

はその後、それをマップ:

public Addresses GetAddress(short id) 
{ 
    entityContext = new SiteDBEntities(); 
    var addressList = entityContext.Addresses.Where(a => a.Id == id).FirstOrDefault(); 

    // Create DTO object 
    AddressesDTO address = new AddressesDTO(); 

    // Map it 
    address.Id = addressList.Id; 
    address.Title = addressList.Title 
    // Go on, it's quite long... 

    entityContext.Dispose(); 
    return address; 
} 

をしかし、あなたが見ることができるように、マッピングプロセスは非常に退屈です。より良い方法はAutomapperです。

1

エンティティデータモデルを使用する場合は、postで私の答えを見てみることをお勧めします。

これで、@AnhTrietのように、ビューに渡す必要があるデータだけを取得するDTOを作成します。クエリをDTOに投影する必要があるたびに、それぞれのプロパティを自分でマップしないようにするには、Automapperを使用することをお勧めします。

public class AddressesManager 
{ 
    public Addresses GetAddress(short id) 
    { 

     using(var entityContext = new SiteDBEntities()) 
     { 
      var address = entityContext.Addresses 
             .Where(a => a.Id == id) 
             .ProjectTo<AddressDTO>() 
             .FirstOrDefault(); 
      return address; 
     } 
    } 
} 

ProjectTo拡張メソッドについて:私はあなたがそれを使用することにした場合、あなたの解決策になるかをお見せしましょう。

+0

あなたの投稿をありがとう。私は現在、コースで勉強しています。私は、Automaperを使用したときに悪い業績について私のグループの人から聞いていました。そこで彼らはカスタムマッピングを使用することに決めました。 – dantey89

+0

DTOに関するあなたのコメントは私にとって有益なものでした。今私はより明確にプログラムのアーキテクチャを理解することができます – dantey89

+0

あなたを歓迎します;)。 Automapperについて、少なくとも私の場合、私はそのような問題を抱えていませんでした。しかし、私は最終的にはSQLに変換されるため、クエリを作成する方法に依存すると思います。また、Linqクエリで非効率的なやり方をしたり、不要なデータをマップしたりすると、パフォーマンスに影響します。 – octavioccl

関連する問題