新しい Windows Azure キャッシュ サービス (プレビュー) を利用したいのですが、この記事に従って、Session を使用してキャッシュに正常に格納および取得することができました。残念ながら、Linq to Sql オブジェクトを Session に格納していますが、現時点では変更できません。Azure キャッシュ サービスを使用してそのようなオブジェクトをセッションに格納しようとすると、次のエラーが発生します。
型 'System.Data.Linq.EntitySet`1[cachetest.Child]' をシリアル化できません。これを DataContractAttribute 属性でマークし、シリアル化するすべてのメンバーを DataMemberAttribute 属性でマークすることを検討してください。型がコレクションの場合は、CollectionDataContractAttribute でマークすることを検討してください。
データ コンテキストに「単方向」シリアル化モードを使用したため、すべての宣言は既に「DataContract」属性と「DataMember」属性で装飾されています (以下のコード サンプルを参照)。
この記事とスタックオーバーフローに関するこの記事と同様のカスタム シリアライザーの使用を検討しましたが、この記事の最後に記載されている正確なエラーと一致するエラーを受け取りました。
Cache の ASP.NET プロバイダーは、バイナリまたはカスタムのシリアル化の種類をサポートしていません。
カスタム シリアライザーはオプションではないため、Windows Azure キャッシングを使用して、Linq to Sql オブジェクト (親子関係を含む) をセッションに保存するにはどうすればよいでしょうか?
以下の問題を示すコードを分割しました。
Linq DataContext:
<?xml version="1.0" encoding="utf-8"?><Database Class="TestModelDataContext" Serialization="Unidirectional" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
<Table Name="" Member="Parents">
<Type Name="Parent">
<Column Member="Name" Type="System.String" CanBeNull="false" />
<Column Member="ParentId" Type="System.Int32" IsPrimaryKey="true" CanBeNull="false" />
<Association Name="Parent_Child" Member="Childs" ThisKey="ParentId" OtherKey="ParentId" Type="Child" />
</Type>
</Table>
<Table Name="" Member="Childs">
<Type Name="Child">
<Column Member="Name" Type="System.String" CanBeNull="false" />
<Column Member="ChildId" Type="System.Int32" IsPrimaryKey="true" CanBeNull="false" />
<Column Member="ParentId" Type="System.Int32" CanBeNull="false" />
<Association Name="Parent_Child" Member="Parent" ThisKey="ParentId" OtherKey="ParentId" Type="Parent" IsForeignKey="true" />
</Type>
</Table>
</Database>
セッションを使用するページ:
namespace cachetest
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Parent newParent = new Parent { Name = "John", ParentId=1 };
Child child1 = new Child { ChildId = 1, Name="John Jr." };
Child child2 = new Child { ChildId = 2, Name="Betty" };
newParent.Childs.Add(child1);
newParent.Childs.Add(child2);
Session["parent"] = newParent;
}
}
Web.Config
(機密データを削除):
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="dataCacheClients" type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere"/>
<section name="cacheDiagnostics" type="Microsoft.ApplicationServer.Caching.AzureCommon.DiagnosticsConfigurationSection, Microsoft.ApplicationServer.Caching.AzureCommon" allowLocation="true" allowDefinition="Everywhere"/>
</configSections>
<connectionStrings>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5"/>
<httpRuntime/>
<sessionState mode="Custom" customProvider="AFCacheSessionStateProvider">
<providers>
<add name="AFCacheSessionStateProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" applicationName="AFCacheSessionState"/>
</providers>
</sessionState>
<pages controlRenderingCompatibilityVersion="4.0"/>
</system.web>
<dataCacheClients>
<dataCacheClient name="default">
<autoDiscover isEnabled="true" identifier="[cachename].cache.windows.net"/>
<securityProperties mode="Message" sslEnabled="false">
<messageSecurity authorizationInfo="[CacheKey]"/>
</securityProperties>
</dataCacheClient>
</dataCacheClients>
</configuration>