2011-12-11 12 views
2

EFからContextオブジェクトをWCFメソッドに渡す必要があります。Entity Framework ContextオブジェクトをWCFに渡す

通常、私はWCFメソッドでContextオブジェクトを作成し、メソッド呼び出しの終了直前に処理します。これはメソッドの大半でうまくいきます。

しかし、一部のルックアップテーブルでキャッシュが有効になっているため、Contextオブジェクト(特にDBContext)をMVCコントローラから特定のWCFメソッドに渡す必要があります。 SqlDependencyにこの特定のオブジェクトを使用するため、上記の文で行うのではなく、この特定のContextオブジェクト(Global.asaxファイルのApplication_Startメソッドで設定したオブジェクト)を渡す必要があります。新しいDBContextオブジェクトを作成しようとすると、データベース呼び出しの前にSqlDependencyを有効にする必要があるというエラーが表示されるため、SqlDependencyを使用できません。

問題は、KnownType属性(DBContextオブジェクト)を正しく宣言していないことがわかっているWCFテストクライアントツールを試してみると、次のエラー(簡略化のため短縮) 。 WCFプロジェクトはうまくコンパイルされることに注意してください。私はWCFサービスでKnownTypeを使用したことがないので、この特定の部分についていくつかの助けが必要です。彼らはすべて単純な型(int、stringなど)でした。

Error: Cannot obtain Metadata from http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex

If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange

Error URI: http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex Metadata contains a reference that cannot be resolved:

私は私のWCFサービスでは、次のOperationContractのコードがあります:私は私のWCFサービスでは、次のDataContractのコードを持っている

[OperationContract] 
     IEnumerable<Category> GetCategories(YeagerTechEntities DbContext); 

を:

namespace YeagerTechModel 
{ 
    [Serializable] 
    [DataContract(IsReference = true)] 
    [KnownType(typeof(YeagerTechEntities))] 
    public partial class Category 
    { 
     public Category() 
     { 
      this.Projects = new HashSet<Project>(); 
     } 

     [DataMember] 
     public short CategoryID { get; set; } 
     [DataMember] 
     public string Description { get; set; } 

     [DataMember] 
     public virtual ICollection<Project> Projects { get; set; } 
    } 

} 

は最後に、次は私のWCFであります方法:

public IEnumerable<YeagerTechModel.Category> GetCategories(YeagerTechEntities DbContext) 
     { 
      //YeagerTechEntities DbContext = new YeagerTechEntities(); 

      DbContext.Configuration.ProxyCreationEnabled = false; 

      IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0).AsCached("Categories").ToList(); 
      //IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0); 

      CloseConnection(DbContext); 

      return category; 
     } 
+0

'null 'を返すようにコードを変更すると、このエラーは消えますか? 'KnownType'も取り除かれたらどうでしょう?一度に1つの潜在的な障害箇所を取り除いて、このようなコードを分割しようとすると、問題を切り分けるのに役立ちます。 –

+0

私は、私が投稿したエラーを得た後、私のDataContractにKnowType属性を入れました。 – sagesky36

+0

私はあなたがインターフェイスのコンテキストを渡すべきではないと思います。私はそれがシリアライズ可能になるとは思わないし、おそらく大きな頭痛を引き起こすでしょう。それを取り除こうとしたことがありますか?他のメソッドを使用して渡すことはできますが、サーバー側でその選択を行う必要があります。 –

答えて

1

レジストリ/サービスロケータのパターンに従ってシングルトンオブジェクトが必要です。このオブジェクトはグローバルオブジェクトへの参照を保持します。たとえば、アプリケーションの開始時には、SqlDependencyを使用してコンテキストにこのオブジェクトを入力し、コントローラのアクションとサービスの操作でレジストリを使用してこのコンテキストにアクセスします。

とにかくこれを非常に注意深く使用してください。 SqlDependencyとEFは、あなたの文脈を長く生き生きとさせるので、素晴らしい演奏をしません。長い生活の文脈はin most cases anti-patternです。キャッシュされたデータをロードするために、そのコンテキストを決して使用しないでください。データの変更やキャッシュされていないリレーションのロードには使用しないでください。エンティティを最初のクエリで非トラッキング(AsNoTracking拡張メソッド)にロードし、そのコンテキストのプロキシ作成と遅延ロードを無効にします。

また、EFでのクエリは常にデータベース内で実行されることに注意してください。私はあなたのAsCachedが何をすることになっているのか分かりませんが、どういうわけか、それはうまくいくとは思えません。おそらく:

var category = DbContext.Categories.Local 
         .Where(p => p.CategoryID > 0) 
         .ToList(); 

私はとEFを使用しません。私はADO.NETとSQLを直接使用します。 EFでキャッシングするには、ほとんどの場合、第2レベルのキャッシュを使用するようにEF Caching providerをチェックします。

+0

Ladislav、あなたのコメントのためにありがとう。 EFキャッシングプロバイダについて読むと、これはやりたいことにはあまりにも複雑なようです。加えて、いくつかは動作し、他のものは動作しません。私はEFがそれ以降のバージョンでそれに組み込まれたキャッシングプロパティを持つまで待つつもりです。 4.0や4.1のフレームワークが出て以来、MSがなぜこのようなことを考えていないのか、私には不思議です。うまくいけば、彼らはすぐにこれを次のフレームワークで実装します。私はNHibernateにSQL Dependencyキャッシュが組み込まれていることを知っています。 – sagesky36

関連する問題