Note
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãµã€ã³ã€ã³ãŸãã¯ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
Durable ãµã³ãã«ã§ã¯ãWindows Communication Foundation (WCF) ã©ã³ã¿ã€ã ãã«ã¹ã¿ãã€ãºããŠãæ°žç¶æ§ã€ã³ã¹ã¿ã³ã¹ ã³ã³ããã¹ããæå¹ã«ããæ¹æ³ã瀺ããŸãã ãããã³ã° ã¹ãã¢ãšããŠãSQL Server 2005 (ãã®å Žå㯠SQL Server 2005 Express) ã䜿çšããŸãã ãã ããã«ã¹ã¿ã ã¹ãã¬ãŒãžæ©æ§ã«ã¢ã¯ã»ã¹ããæ¹æ³ã瀺ããŸãã
泚
ãã®ãµã³ãã«ã®ã»ããã¢ããæé ãšãã«ãæé ã«ã€ããŠã¯ããã®èšäºã®æåŸãåç §ããŠãã ããã
ãã®ãµã³ãã«ã«ã¯ãWCF ã®ãã£ãã« ã¬ã€ã€ãŒãšãµãŒãã¹ ã¢ãã« ã¬ã€ã€ãŒã®äž¡æ¹ã®æ¡åŒµãå«ãŸããŠããŸãã ãããã£ãŠãå®è£ ã®è©³çްã«é²ãåã«åºã«ãªãæŠå¿µãçè§£ããå¿ èŠããããŸãã
æ°žç¶æ§ã€ã³ã¹ã¿ã³ã¹ ã³ã³ããã¹ãã¯ãçŸå®ã®ã±ãŒã¹ã§ãé »ç¹ã«èµ·ãããããã®ã§ãã ããšãã°ãã·ã§ããã³ã° ã«ãŒã ã¢ããªã±ãŒã·ã§ã³ã«ã¯ãè²·ãç©ãäžæããŠãå¥ã®æ¥ã«åéã§ããæ©èœãçšæãããŠããŸãã ãã®ãããã·ã§ããã³ã° ã«ãŒãã«ç¿æ¥ã¢ã¯ã»ã¹ãããšãå ã®ã³ã³ããã¹ãã埩å ãããŸãã æ¥ç¶ãåæãããŠããéãã·ã§ããã³ã° ã«ãŒã ã¢ããªã±ãŒã·ã§ã³ (ãµãŒããŒäž) ã¯ã·ã§ããã³ã° ã«ãŒãã®ã€ã³ã¹ã¿ã³ã¹ãä¿æããªãããšã«æ³šæããŠãã ããã ãã®ä»£ãããç¶æ ãæ°žç¶çãªã¹ãã¬ãŒãž ã¡ãã£ã¢ã«ä¿æãã埩å ãããã³ã³ããã¹ãã®æ°ããã€ã³ã¹ã¿ã³ã¹ãæ§ç¯ãããšãã«ãã®ç¶æ ã䜿çšããŸãã ãããã£ãŠãåãã³ã³ããã¹ãã«å¯ŸããŠãµãŒãã¹ãæäŸã§ãããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ã¯ã以åã®ã€ã³ã¹ã¿ã³ã¹ãšåãã§ã¯ãããŸãã (ã€ãŸããã¡ã¢ãª ã¢ãã¬ã¹ãåãã§ã¯ãããŸãã)ã
æ°žç¶æ§ã€ã³ã¹ã¿ã³ã¹ ã³ã³ããã¹ãã¯ãã³ã³ããã¹ã ID ãã¯ã©ã€ã¢ã³ããšãµãŒãã¹éã§äº€æããããã®ç°¡åãªãããã³ã«ã«ãã£ãŠå¯èœã«ãªããŸãã ãã®ã³ã³ããã¹ã ID ã¯ã¯ã©ã€ã¢ã³ãäžã§äœæããããµãŒãã¹ã«è»¢éãããŸãã ãµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ãäœæããããšããµãŒãã¹äžã®ã©ã³ã¿ã€ã ã¯ãæ°žç¶ã¹ãã¬ãŒãž (æ¢å®ã§ã¯ SQL Server 2005 ã®ããŒã¿ããŒã¹) äžã§æ°žç¶åãããŠããããã®ã³ã³ããã¹ã ID ã«å¯Ÿå¿ããç¶æ ãèªã¿èŸŒãããšããŸãã å©çšã§ããç¶æ ããªãå Žåã¯ãæ°ããã€ã³ã¹ã¿ã³ã¹ã«æ¢å®ã®ç¶æ ãèšå®ãããŸãã ãµãŒãã¹å®è£ ã¯ãã«ã¹ã¿ã 屿§ã䜿çšããŠãµãŒãã¹å®è£ ã®ç¶æ ã倿Žããæäœã®è©³çްãæå®ããã©ã³ã¿ã€ã ããã®æäœãåŒã³åºããåŸã«ãµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ãä¿åã§ããããã«ããŸãã
åã®èª¬æãããç®æšãéæããããã®æé ã¯å€§ããæ¬¡ã® 2 ã€ã«åããããŸãã
- ãããã¯ãŒã¯ã«åºåãããã¡ãã»ãŒãžããã³ã³ããã¹ã ID ãå«ãŸããããã«å€æŽããŸãã
- ãµãŒãã¹åŽã®ããŒã«ã«åäœã倿ŽããŠãã«ã¹ã¿ã ã®ã€ã³ã¹ã¿ã³ã¹åããžãã¯ãå®è£ ããŸãã
ãã®äžèЧã®åè ã®æé ã¯ããããã¯ãŒã¯äžã®ã¡ãã»ãŒãžã«åœ±é¿ãããããã«ã¹ã¿ã ãã£ãã«ãšããŠå®è£ ãããã£ãã« ã¬ã€ã€ãŒã«ããã¯ããå¿ èŠããããŸãã åŸè ã®æé ã圱é¿ãåãŒãã®ã¯ããµãŒãã¹ã®ããŒã«ã«åäœã ãã§ãããããã£ãŠãããã€ãã®ãµãŒãã¹æ¡åŒµãã€ã³ããæ¡åŒµããããšã«ãã£ãŠå®è£ ã§ããŸãã 以éã®ã»ã¯ã·ã§ã³ã§ã¯ãããããããããã®æ¡åŒµã«ã€ããŠèª¬æããŸãã
æ°žç¶ç㪠InstanceContext ãã£ãã«
æåã«ããã£ãã« ã¬ã€ã€ã®æ¡åŒµã«ã€ããŠèããŸãã ã«ã¹ã¿ã ãã£ãã«ãèšè¿°ããæåã®æé ãšããŠããã£ãã«ã®éä¿¡æ§é ãæ±ºå®ããŸãã æ°ããã¯ã€ã€ ãããã³ã«ãå°å
¥ããéã«ã¯ããã£ãã«ã¯ãã£ãã« ã¹ã¿ãã¯å
ã®ä»ã®ã»ãšãã©ãã¹ãŠã®ãã£ãã«ã«å¯Ÿå¿ããå¿
èŠããããŸãã ãã®ããããã¹ãŠã®ã¡ãã»ãŒãžäº€æãã¿ãŒã³ããµããŒãããå¿
èŠããããŸãã ãã ãããã£ãã«ã®äžå¿çãªæ©èœã¯éä¿¡æ§é ã«é¢ä¿ãªãåãã§ãã å
·äœçã«ã¯ãã³ã³ããã¹ã ID ãã¯ã©ã€ã¢ã³ãåŽããã¡ãã»ãŒãžã«æžã蟌ã¿ããµãŒãã¹åŽãããã®ã¡ãã»ãŒãžã®ã³ã³ããã¹ã ID ãèªã¿åã£ãŠäžäœã¬ãã«ã«æž¡ããŸãã ãã®ããããã¹ãŠã®æ°žç¶æ§ã€ã³ã¹ã¿ã³ã¹ ã³ã³ããã¹ã ãã£ãã«ã®å®è£
ã«å¯ŸããŠæœè±¡åºæ¬ã¯ã©ã¹ãšããŠåäœãããDurableInstanceContextChannelBase ã¯ã©ã¹ãäœæãããŸãã ãã®ã¯ã©ã¹ã«ã¯ãå
±éã¹ããŒã ãã·ã³ã®ç®¡çæ©èœãšä¿è·ããã 2 ã€ã®ã¡ã³ããå«ãŸããããã«ãã£ãŠã³ã³ããã¹ãæ
å ±ãã¡ãã»ãŒãžã«é©çšããããã¡ãã»ãŒãžããã³ã³ããã¹ãæ
å ±ãèªã¿åã£ããããŸãã
class DurableInstanceContextChannelBase
{
//âŠ
protected void ApplyContext(Message message)
{
//âŠ
}
protected string ReadContextId(Message message)
{
//âŠ
}
}
ããã 2 ã€ã®ã¡ãœããã¯ãIContextManager å®è£
ã䜿çšããŠãã¡ãã»ãŒãžãžã®ã³ã³ããã¹ã ID ã®æžã蟌ã¿ãšãã¡ãã»ãŒãžããã®ã³ã³ããã¹ã ID ã®èªã¿åããè¡ããŸã (IContextManager ã¯ããã¹ãŠã®ã³ã³ããã¹ã ãããŒãžã£ãŒã®ã³ã³ãã©ã¯ãã®å®çŸ©ã«äœ¿çšãããã«ã¹ã¿ã ã€ã³ã¿ãŒãã§ã€ã¹ã§ã)ããã£ãã«ã§ã¯ããã®ã³ã³ããã¹ã ID ããã«ã¹ã¿ã SOAP ããããŒã HTTP ã¯ãã㌠ããããŒã®ã©ã¡ããã«å«ããããšãã§ããŸãã åã³ã³ããã¹ã ãããŒãžã£ã®å®è£
ã¯ãContextManagerBase ã¯ã©ã¹ãç¶æ¿ããŸãããã®ã¯ã©ã¹ã«ã¯ããã¹ãŠã®ã³ã³ããã¹ã ãããŒãžã£ã«ã€ããŠã®å
±éæ©èœãå«ãŸããŠããŸãã ãã®ã¯ã©ã¹ã® GetContextId ã¡ãœããã¯ãã³ã³ããã¹ã ID ãã¯ã©ã€ã¢ã³ãåŽã§çæããéã«äœ¿çšãããŸãã ã³ã³ããã¹ã ID ãæåã«çæããããšããã®ã¡ãœããã¯ãããããã¹ã ãã¡ã€ã«ã«ä¿åããŸããããã¹ã ãã¡ã€ã«ã®ååã¯ããªã¢ãŒã ãšã³ããã€ã³ã ã¢ãã¬ã¹ã«ãã£ãŠäœæãããŸã (éåžžã® URI ã«å«ãŸããããã¡ã€ã«åãšããŠç¡å¹ãªæåã¯ã@ æåã«çœ®ãæããããŸã)ã
ã³ã³ããã¹ã ID ãåŸã§åããªã¢ãŒã ãšã³ããã€ã³ãã§å¿ èŠã«ãªããšããã®ã¡ãœããã¯é©åãªãã¡ã€ã«ãååšãããã©ããããã§ãã¯ããŸãã ãããåœãŠã¯ãŸãå Žåãã³ã³ããã¹ã ID ãèªã¿åã£ãŠè¿ããŸãã ååšããªãå Žåã¯ãæ°ããçæãããã³ã³ããã¹ã ID ãè¿ããŠããããã¡ã€ã«ã«ä¿åããŸãã æ¢å®ã®æ§æã§ã¯ããããã®ãã¡ã€ã«ã¯çŸåšã®ãŠãŒã¶ãŒã®äžæãã£ã¬ã¯ããªå ã«ãã ContextStore ãã£ã¬ã¯ããªã«ãããŸãã ãã ãããã®å Žæã¯ãã€ã³ãèŠçŽ ã䜿çšããŠæ§æã§ããŸãã
ã³ã³ããã¹ã ID ã®è»¢éã«äœ¿çšãããæ©æ§ã¯æ§æå¯èœã§ãã HTTP ã¯ãã㌠ããããŒãããŸãã¯ã«ã¹ã¿ã SOAP ããããŒã®ã©ã¡ããã«èšè¿°ã§ããŸãã ã«ã¹ã¿ã SOAP ããããŒã«èšè¿°ããå Žåã¯ããã®ãããã³ã«ã HTTP 以å€ã®ãããã³ã« (TCP ã NamedPipes ãªã©) ã§äœ¿çšã§ããŸãã ãããã® 2 ã€ã®ãªãã·ã§ã³ã¯ãMessageHeaderContextManager ãš HttpCookieContextManager ãšããååã® 2 ã€ã®ã¯ã©ã¹ã«å®è£
ãããŸãã
ãããã®ã¯ã©ã¹ã¯ã©ã¡ãããã³ã³ããã¹ã ID ãã¡ãã»ãŒãžã«é©åã«æžã蟌ã¿ãŸãã ããšãã° MessageHeaderContextManager ã¯ã©ã¹ã§ã¯ãWriteContext ã¡ãœããã§ SOAP ããããŒã«æžã蟌ã¿ãŸãã
public override void WriteContext(Message message)
{
string contextId = this.GetContextId();
MessageHeader contextHeader =
MessageHeader.CreateHeader(DurableInstanceContextUtility.HeaderName,
DurableInstanceContextUtility.HeaderNamespace,
contextId,
true);
message.Headers.Add(contextHeader);
}
ApplyContext ã¯ã©ã¹å
ã® ReadContextId ã¡ãœãããš DurableInstanceContextChannelBase ã¡ãœããã¯ããããã IContextManager.ReadContext ãš IContextManager.WriteContext ãåŒã³åºããŸãã ãã ãããããã®ã³ã³ããã¹ã ãããŒãžã£ã¯ DurableInstanceContextChannelBase ã¯ã©ã¹ã«ãã£ãŠçŽæ¥äœæãããããã§ã¯ãããŸããã 代ããã« ContextManagerFactory ã¯ã©ã¹ã䜿çšããŠãã®åŠçãè¡ãããŸãã
IContextManager contextManager =
ContextManagerFactory.CreateContextManager(contextType,
this.contextStoreLocation,
this.endpointAddress);
ApplyContext ã¡ãœããã¯éä¿¡ãã£ãã«ã«ãã£ãŠåŒã³åºãããŸãã ãã®ã¡ãœããã¯ãã³ã³ããã¹ã ID ãéä¿¡ã¡ãã»ãŒãžã«æ¿å
¥ããŸãã
ReadContextId ã¡ãœããã¯åä¿¡ãã£ãã«ã«ãã£ãŠåŒã³åºãããŸãã ãã®ã¡ãœããã¯ãåä¿¡ã¡ãã»ãŒãžå
ã§ã³ã³ããã¹ã ID ã䜿çšã§ããããšã確èªããProperties ã¯ã©ã¹ã® Message ã³ã¬ã¯ã·ã§ã³ã«ã³ã³ããã¹ã ID ã远å ããŸãã ããã«ãã³ã³ããã¹ã ID ã®èªã¿åãã§ãšã©ãŒãçºçããå Žå㯠CommunicationException ãã¹ããŒãããã£ãã«ãäžæ¢ããŸãã
message.Properties.Add(DurableInstanceContextUtility.ContextIdProperty, contextId);
次ã«é²ãåã«ãProperties ã¯ã©ã¹ã® Message ã³ã¬ã¯ã·ã§ã³ã®äœ¿ç𿹿³ã«ã€ããŠçè§£ããããšãéèŠã§ãã éåžžããã® Properties ã³ã¬ã¯ã·ã§ã³ã¯ããã£ãã« ã¬ã€ã€ã®ããŒã¿ãäžäœã¬ãã«ããäžäœã¬ãã«ã«æž¡ããšãã«äœ¿çšãããŸãã ãã®æ¹æ³ã«ãããå¿
èŠãªããŒã¿ãããããã³ã«ã®è©³çްã«é¢ä¿ãªãäžè²«ããæ¹æ³ã§äžäœã¬ãã«ã«æž¡ãããšãã§ããŸãã ã€ãŸãããã£ãã« ã¬ã€ã€ãŒã¯ã³ã³ããã¹ã ID ããSOAP ããããŒãšããŠã HTTP ã¯ãã㌠ããããŒãšããŠãéåä¿¡ã§ããŸãã ããããäžäœã¬ãã«ã§ã¯ãããã詳现ãèªèããå¿
èŠã¯ãããŸããããã£ãã« ã¬ã€ã€ã«ããããã®æ
å ±ã Properties ã³ã¬ã¯ã·ã§ã³ã§äœ¿çšã§ããããã§ãã
DurableInstanceContextChannelBase ã¯ã©ã¹ãé
åããããå¿
èŠãª 10 ã®ã€ã³ã¿ãŒãã§ã€ã¹ (IOutputChannelãIInputChannelãIOutputSessionChannelãIInputSessionChannelãIRequestChannelãIReplyChannelãIRequestSessionChannelãIReplySessionChannelãIDuplexChannelãããã³ IDuplexSessionChannel) ã®ãã¹ãŠãå®è£
ããå¿
èŠããããŸãã ãããã¯ã䜿çšå¯èœãªãã¹ãŠã®ã¡ãã»ãŒãžäº€æãã¿ãŒã³ (ããŒã¿ã°ã©ã ãäžæ¹åãåæ¹åãããã³ã»ãã·ã§ã³ãã« ããªãšãŒã·ã§ã³) ãšäŒŒãŠããŸãã ãããã®åå®è£
ã§ã¯ãåèšã®åºæ¬ã¯ã©ã¹ãç¶æ¿ããApplyContext ãš ReadContextId ãé©åã«åŒã³åºããŸãã ããšãã°ãIOutputChannel ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãã DurableInstanceContextOutputChannel ã¯ãã¡ãã»ãŒãžãéä¿¡ããåã¡ãœãããã ApplyContext ã¡ãœãããåŒã³åºããŸãã
public void Send(Message message, TimeSpan timeout)
{
// Apply the context information before sending the message.
this.ApplyContext(message);
//âŠ
}
ããã«å¯ŸããDurableInstanceContextInputChannel ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ãã IInputChannel ã§ã¯ãã¡ãã»ãŒãžãåä¿¡ããåã¡ãœããã§ ReadContextId ã¡ãœãããåŒã³åºããŸãã
public Message Receive(TimeSpan timeout)
{
//âŠ
ReadContextId(message);
return message;
}
ãããã®ãã£ãã«å®è£ ã¯ããã以å€ã«ã¯ããã£ãã« ã¹ã¿ãã¯å ã§ãã£ãã«å®è£ ã®äžã«ãããã£ãã«ãžã®ã¡ãœããåŒã³åºãã代è¡ããŸãã ãã ããã»ãã·ã§ã³ãã« ããªãšãŒã·ã§ã³ã«ã¯ãã»ãã·ã§ã³äœæã®åºã«ãªãæåã®ã¡ãã»ãŒãžã«å¯ŸããŠã®ã¿ã³ã³ããã¹ã ID ã®éä¿¡ãšèªã¿åããèš±å¯ãããåºæ¬çãªããžãã¯ããããŸãã
if (isFirstMessage)
{
//âŠ
this.ApplyContext(message);
isFirstMessage = false;
}
ããããã£ãã«å®è£
ã¯ããã®åŸãDurableInstanceContextBindingElement ã¯ã©ã¹ãš DurableInstanceContextBindingElementSection ã¯ã©ã¹ã«ãã£ãŠ WCF ãã£ãã« ã©ã³ã¿ã€ã ã«é©åã«è¿œå ãããŸãã ãã€ã³ãã£ã³ã°èŠçŽ ãšãã€ã³ãã£ã³ã°èŠçŽ ã»ã¯ã·ã§ã³ã®è©³çްã«ã€ããŠã¯ãHttpCookieSession ãã£ãã«ã®ãµã³ãã«ã«é¢ããããã¥ã¡ã³ããåç
§ããŠãã ããã
ãµãŒãã¹ ã¢ãã« ã¬ã€ã€ã®æ¡åŒµ
ã³ã³ããã¹ã ID ããã£ãã« ã¬ã€ã€ãééãããšãã€ã³ã¹ã¿ã³ã¹åãã«ã¹ã¿ãã€ãºããããã«ãµãŒãã¹åŽã®åäœãå®è£ ã§ããŸãã ãã®ãµã³ãã«ã§ã¯ãèšæ¶åãããŒãžã£ã䜿çšããŠæ°žç¶ã¹ãã¢ããã®ç¶æ ã®èªã¿èŸŒã¿ãšãæ°žç¶ã¹ãã¢ãžã®ç¶æ ã®ä¿åãè¡ãããŸãã åè¿°ã®ããã«ããã®ãµã³ãã«ã«ã¯ãããã³ã° ã¹ãã¢ãšã㊠SQL Server 2005 ã䜿çšããèšæ¶åãããŒãžã£ãçšæãããŠããŸãã ãã ãããã®æ¡åŒµã«å¯ŸããŠã«ã¹ã¿ã ã¹ãã¬ãŒãžæ©æ§ã远å ããããšãã§ããŸãã ãããè¡ãã«ã¯ããã¹ãŠã®èšæ¶åãããŒãžã£ãå®è£ ããå¿ èŠã®ãããããªã㯠ã€ã³ã¿ãŒãã§ã€ã¹ã宣èšããŸãã
public interface IStorageManager
{
object GetInstance(string contextId, Type type);
void SaveInstance(string contextId, object state);
}
SqlServerStorageManager ã¯ã©ã¹ã«ã¯ãæ¢å®ã® IStorageManager å®è£
ãå«ãŸããŸãã
SaveInstance ã¡ãœããã§ã¯ãæå®ããããªããžã§ã¯ãã XmlSerializer ã䜿çšããŠã·ãªã¢ã«åãããSQL Server ããŒã¿ããŒã¹ã«ä¿åãããŸãã
XmlSerializer serializer = new XmlSerializer(state.GetType());
string data;
using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
{
serializer.Serialize(writer, state);
data = writer.ToString();
}
using (SqlConnection connection = new SqlConnection(GetConnectionString()))
{
connection.Open();
string update = @"UPDATE Instances SET Instance = @instance WHERE ContextId = @contextId";
using (SqlCommand command = new SqlCommand(update, connection))
{
command.Parameters.Add("@instance", SqlDbType.VarChar, 2147483647).Value = data;
command.Parameters.Add("@contextId", SqlDbType.VarChar, 256).Value = contextId;
int rows = command.ExecuteNonQuery();
if (rows == 0)
{
string insert = @"INSERT INTO Instances(ContextId, Instance) VALUES(@contextId, @instance)";
command.CommandText = insert;
command.ExecuteNonQuery();
}
}
}
GetInstance ã¡ãœããã§ã¯ãã·ãªã¢ã«åãããããŒã¿ãç¹å®ã®ã³ã³ããã¹ã ID çšã«èªã¿åãããããããäœæããããªããžã§ã¯ããåŒã³åºãå
ã«è¿ãããŸãã
object data;
using (SqlConnection connection = new SqlConnection(GetConnectionString()))
{
connection.Open();
string select = "SELECT Instance FROM Instances WHERE ContextId = @contextId";
using (SqlCommand command = new SqlCommand(select, connection))
{
command.Parameters.Add("@contextId", SqlDbType.VarChar, 256).Value = contextId;
data = command.ExecuteScalar();
}
}
if (data != null)
{
XmlSerializer serializer = new XmlSerializer(type);
using (StringReader reader = new StringReader((string)data))
{
object instance = serializer.Deserialize(reader);
return instance;
}
}
ãã®èšæ¶åãããŒãžã£ãçŽæ¥ã€ã³ã¹ã¿ã³ã¹åããããšã¯ã§ããŸããã ãã®ä»£ããã«ãStorageManagerFactory ã¯ã©ã¹ã䜿çšããŠãèšæ¶åãããŒãžã£ã®äœæã«é¢ãã詳现ããæœåºããŸãã ãã®ã¯ã©ã¹ã«ã¯ãæå®ãããåã®èšæ¶åãããŒãžã£ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããã1 ã€ã®éçã¡ã³ã GetStorageManager ããããŸãã åãã©ã¡ãŒã¿ãŒã null ã®å Žåããã®ã¡ãœããã¯æ¢å®ã® SqlServerStorageManager ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŠè¿ããŸãã ããã«æå®ãããåãæ€èšŒããŠãããã IStorageManager ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŠããããšã確èªããŸãã
public static IStorageManager GetStorageManager(Type storageManagerType)
{
IStorageManager storageManager = null;
if (storageManagerType == null)
{
return new SqlServerStorageManager();
}
else
{
object obj = Activator.CreateInstance(storageManagerType);
// Throw if the specified storage manager type does not
// implement IStorageManager.
if (obj is IStorageManager)
{
storageManager = (IStorageManager)obj;
}
else
{
throw new InvalidOperationException(
ResourceHelper.GetString("ExInvalidStorageManager"));
}
return storageManager;
}
}
æ°žç¶ã¹ãã¬ãŒãžã®ã€ã³ã¹ã¿ã³ã¹ã®èªã¿åããæžã蟌ã¿ã«å¿ èŠãªã€ã³ãã©ã¹ãã©ã¯ãã£ãå®è£ ããŸãã ããã§ããµãŒãã¹åŽã®åäœã倿Žããããã«å¿ èŠãªæé ãè¡ãå¿ èŠããããŸãã
ãã®åŠçã®æåã®æé ãšããŠããã£ãã« ã¬ã€ã€ãééããã³ã³ããã¹ã ID ãçŸåšã® InstanceContext ã«ä¿åããå¿ èŠããããŸãã InstanceContext ã¯ãWCF ãã£ã¹ãããã£ãŒãšãµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹éã®ãªã³ã¯ãšããŠæ©èœããã©ã³ã¿ã€ã ã³ã³ããŒãã³ãã§ãã ããã䜿çšãããšã远å ã®ç¶æ ãšåäœããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ã«æäŸã§ããŸãã ã»ãã·ã§ã³ã®å€ãéä¿¡ã§ã¯ãã³ã³ããã¹ã ID ã¯æåã®ã¡ãã»ãŒãžã ãã«å«ãŸããŠéä¿¡ãããã®ã§ããããéèŠã«ãªããŸãã
WCF ã§ã¯ãæ¡åŒµå¯èœãªããžã§ã¯ã ãã¿ãŒã³ã䜿çšããŠæ°ããç¶æ ãšåäœã远å ããããšã§ãInstanceContext ã©ã³ã¿ã€ã ã³ã³ããŒãã³ããæ¡åŒµã§ããŸãã æ¡åŒµå¯èœãªããžã§ã¯ã ãã¿ãŒã³ã¯ãæ¢åã®ã©ã³ã¿ã€ã ã¯ã©ã¹ã«æ°ããæ©èœãä»ãå ããŠæ¡åŒµããããããŸãã¯ãªããžã§ã¯ãã«æ°ããç¶æ ã®æ©èœã远å ããããã« WCF ã§äœ¿çšãããŸãã æ¡åŒµå¯èœãªããžã§ã¯ã ãã¿ãŒã³ã«ã¯ãIExtensibleObject<T>ãIExtension<T>ãIExtensionCollection<T> ã® 3 ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ããããŸãã
IExtensibleObject<T> ã€ã³ã¿ãŒãã§ã€ã¹ã¯ãæ©èœãã«ã¹ã¿ãã€ãºããããã®æ¡åŒµãå¯èœãªãªããžã§ã¯ãã«ãã£ãŠå®è£ ãããŸãã
IExtension<T> ã€ã³ã¿ãŒãã§ã€ã¹ã¯ãT åã®ã¯ã©ã¹ã®æ¡åŒµã§ãããªããžã§ã¯ãã«ãã£ãŠå®è£ ãããŸãã
IExtensionCollection<T> ã€ã³ã¿ãŒãã§ã€ã¹ã¯ IExtensions ã®ã³ã¬ã¯ã·ã§ã³ã§ãåããšã« IExtensions ãååŸã§ããŸãã
ãã®ãããIExtension ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããŠãã³ã³ããã¹ã ID ãä¿åããããã«å¿ èŠãªç¶æ ãå®çŸ©ãããInstanceContextExtension ã¯ã©ã¹ãäœæããå¿ èŠããããŸãã ãã®ã¯ã©ã¹ã§ã¯ããã«ã䜿çšãããèšæ¶åãããŒãžã£ãä¿æããç¶æ ãæäŸãããŸãã æ°ããç¶æ ãä¿åãããåŸã§ã¯ããã®ç¶æ ã倿Žã§ããŸããã ãããã£ãŠãã€ã³ã¹ã¿ã³ã¹ãäœæãããéãèªã¿åãå°çšã®ããããã£ã䜿çšããŠã®ã¿ã¢ã¯ã»ã¹å¯èœã«ãªã£ãæç¹ã§ãç¶æ ãã€ã³ã¹ã¿ã³ã¹ã«æäŸãããä¿åãããŸãã
// Constructor
public DurableInstanceContextExtension(string contextId,
IStorageManager storageManager)
{
this.contextId = contextId;
this.storageManager = storageManager;
}
// Read only properties
public string ContextId
{
get { return this.contextId; }
}
public IStorageManager StorageManager
{
get { return this.storageManager; }
}
InstanceContextInitializer ã¯ã©ã¹ã¯ IInstanceContextInitializer ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããäœæããã InstanceContext ã® Extensions ã³ã¬ã¯ã·ã§ã³ã«ã€ã³ã¹ã¿ã³ã¹ ã³ã³ããã¹ãæ¡åŒµã远å ããŸãã
public void Initialize(InstanceContext instanceContext, Message message)
{
string contextId =
(string)message.Properties[DurableInstanceContextUtility.ContextIdProperty];
DurableInstanceContextExtension extension =
new DurableInstanceContextExtension(contextId,
storageManager);
instanceContext.Extensions.Add(extension);
}
æ¢ã«èª¬æããããã«ãã³ã³ããã¹ã ID 㯠Properties ã¯ã©ã¹ã® Message ã³ã¬ã¯ã·ã§ã³ããèªã¿åãããæ¡åŒµã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã«æž¡ãããŸãã ããã«ãã£ãŠãã¬ã€ã€éã§æ
å ±ã亀æããå Žåã®äžè²«æ§ã®ããæ¹æ³ã瀺ãããŸãã
次ã®éèŠãªæé ã¯ããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ã®äœææé ããªãŒããŒã©ã€ãããããšã§ãã WCF ã䜿çšãããšãã«ã¹ã¿ãã€ãºãããã€ã³ã¹ã¿ã³ã¹ååäœãå®è£
ããIInstanceProvider ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠããããã©ã³ã¿ã€ã ã«ããã¯ã§ããŸãã æ°ãã InstanceProvider ã¯ã©ã¹ããã®åŠçãè¡ãããã«å®è£
ãããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãã€ã³ã¹ã¿ã³ã¹ ãããã€ããŒããèŠæ±ããããµãŒãã¹ã®çš®é¡ãåãå
¥ããããŸãã ããã¯ãåŸã§æ°ããã€ã³ã¹ã¿ã³ã¹ã®äœæã«äœ¿çšãããŸãã
GetInstance å®è£
ã§ã¯ãæ°žç¶ããã€ã³ã¹ã¿ã³ã¹ãæ€çŽ¢ããèšæ¶åãããŒãžã£ãŒã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããŸãã
null ãè¿ãããå Žåããã®ãµãŒãã¹ã®çš®é¡ã®æ°ããã€ã³ã¹ã¿ã³ã¹ãã€ã³ã¹ã¿ã³ã¹åãããåŒã³åºãå
ã«è¿ãããŸãã
public object GetInstance(InstanceContext instanceContext, Message message)
{
object instance = null;
DurableInstanceContextExtension extension =
instanceContext.Extensions.Find<DurableInstanceContextExtension>();
string contextId = extension.ContextId;
IStorageManager storageManager = extension.StorageManager;
instance = storageManager.GetInstance(contextId, serviceType);
instance ??= Activator.CreateInstance(serviceType);
return instance;
}
次ã®éèŠãªæé ã¯ãInstanceContextExtension ã¯ã©ã¹ãInstanceContextInitializer ã¯ã©ã¹ãInstanceProvider ã¯ã©ã¹ããµãŒãã¹ ã¢ãã« ã©ã³ã¿ã€ã ã«ã€ã³ã¹ããŒã«ããããšã§ãã ã«ã¹ã¿ã 屿§ã䜿çšãããšããµãŒãã¹å®è£
ã¯ã©ã¹ã®è©³çްãæå®ããŠãåäœãã€ã³ã¹ããŒã«ã§ããŸãã
DurableInstanceContextAttribute ã«ã¯ãã®å±æ§ã®å®è£
ãå«ãŸãããµãŒãã¹åŽã®ã©ã³ã¿ã€ã å
šäœãæ¡åŒµã§ããããã«ããããã« IServiceBehavior ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŸãã
ãã®ã¯ã©ã¹ã«ã¯ã䜿çšãããèšæ¶åãããŒãžã£ã®åãåãå
¥ããããããã£ããããŸãã ãã®ããã«å®è£
ãããšããŠãŒã¶ãŒã¯ç¬èªã® IStorageManager å®è£
ããã®å±æ§ã®ãã©ã¡ãŒã¿ãŒãšããŠæå®ã§ããŸãã
ApplyDispatchBehavior å®è£
ã§ã¯ãçŸåšã® InstanceContextMode 屿§ã® ServiceBehavior ãæ€èšŒãããŸãã ãã®ããããã£ã Singleton ã«èšå®ãããŠããå Žåãæ°žç¶æ§ã€ã³ã¹ã¿ã³ã¹ãæå¹åã§ãããInvalidOperationException ãã¹ããŒãããŠãã¹ãã«éç¥ãããŸãã
ServiceBehaviorAttribute serviceBehavior =
serviceDescription.Behaviors.Find<ServiceBehaviorAttribute>();
if (serviceBehavior != null &&
serviceBehavior.InstanceContextMode == InstanceContextMode.Single)
{
throw new InvalidOperationException(
ResourceHelper.GetString("ExSingletonInstancingNotSupported"));
}
ãã®åŸãèšæ¶åãããŒãžã£ã®ã€ã³ã¹ã¿ã³ã¹ãã€ã³ã¹ã¿ã³ã¹ ã³ã³ããã¹ãã®åæååãããã³ã€ã³ã¹ã¿ã³ã¹ ãããã€ããäœæãããåãšã³ããã€ã³ãçšã«äœæããã DispatchRuntime ã«ã€ã³ã¹ããŒã«ãããŸãã
IStorageManager storageManager =
StorageManagerFactory.GetStorageManager(storageManagerType);
InstanceContextInitializer contextInitializer =
new InstanceContextInitializer(storageManager);
InstanceProvider instanceProvider =
new InstanceProvider(description.ServiceType);
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceContextInitializers.Add(contextInitializer);
ed.DispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
ãããŸã§ãèŠçŽãããšããã®ãµã³ãã«ã§ã¯ãã«ã¹ã¿ã ã³ã³ããã¹ã ID ã亀æããããã«ã«ã¹ã¿ã ã¯ã€ã€ ãããã³ã«ãæå¹åãããã£ãã«ãäœæããŸããããŸããæ°žç¶ã¹ãã¬ãŒãžã®ã€ã³ã¹ã¿ã³ã¹ãèªã¿èŸŒãããã«ãæ¢å®ã®ã€ã³ã¹ã¿ã³ã¹ååäœãäžæžãããŸããã
æ®ãã®æé ã¯ããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ãæ°žç¶ã¹ãã¬ãŒãžã«ä¿åããããšã§ãã æ¢ã«èª¬æãããšãããIStorageManager å®è£
ã«ç¶æ
ãä¿åããã«ã¯ããããããå¿
èŠãªæ©èœããããŸãã æ¬¡ã«ãããã WCF ã©ã³ã¿ã€ã ãšçµ±åããå¿
èŠããããŸãã ãããè¡ãã«ã¯ããµãŒãã¹å®è£
ã¯ã©ã¹ã®ã¡ãœããã«é©çšå¯èœãªå¥ã®å±æ§ãå¿
èŠã§ãã ã€ãŸããã®å±æ§ã¯ããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ã®ç¶æ
ã倿Žããã¡ãœããã«é©çšã§ããããšãå¿
èŠã§ãã
ãã®æ©èœã¯ãSaveStateAttribute ã¯ã©ã¹ã«å®è£
ãããŠããŸãã ããã«ã¯ãåæäœã® WCF ã©ã³ã¿ã€ã ã倿Žãã IOperationBehavior ã¯ã©ã¹ãå®è£
ãããŠããŸãã ãã®å±æ§ã§ã¡ãœãããããŒã¯ããããšãé©å㪠ApplyBehavior ãäœæãããéã«ãWCF ã©ã³ã¿ã€ã ã§ DispatchOperation ã¡ãœãããåŒã³åºãããŸãã ãã®ã¡ãœããã®å®è£
ã«ã¯ã次㮠1 è¡ã®ã³ãŒãããããŸãã
dispatch.Invoker = new OperationInvoker(dispatch.Invoker);
ãã®æé ã«ãã OperationInvoker åã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããäœæããã Invoker ã® DispatchOperation ããããã£ã«å²ãåœãŠãããŸãã
OperationInvoker ã¯ã©ã¹ã¯ãDispatchOperation çšã«äœæãããæ¢å®ã®æäœåŒã³åºãã®ã©ãããŒã§ãã ãã®ã¯ã©ã¹ã¯ã IOperationInvoker ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŸãã
Invoke ã¡ãœããã®å®è£
ã§ã¯ãå®éã®ã¡ãœããåŒã³åºãã¯å
éšã®æäœåŒã³åºãã§ä»£è¡ãããŸãã ãã ãããã®çµæãè¿ãããåã« InstanceContext ã®èšæ¶åãããŒãžã£ã䜿çšããããµãŒãã¹ ã€ã³ã¹ã¿ã³ã¹ãä¿åãããŸãã
object result = innerOperationInvoker.Invoke(instance,
inputs, out outputs);
// Save the instance using the storage manager saved in the
// current InstanceContext.
InstanceContextExtension extension =
OperationContext.Current.InstanceContext.Extensions.Find<InstanceContextExtension>();
extension.StorageManager.SaveInstance(extension.ContextId, instance);
return result;
æ¡åŒµæ©èœã®äœ¿çš
ãã£ãã« ã¬ã€ã€ãŒãšãµãŒãã¹ ã¢ãã« ã¬ã€ã€ãŒã®äž¡æ¹ã®æ¡åŒµãå®äºãããããã WCF ã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšã§ããããã«ãªããŸããã ãµãŒãã¹ã§ã¯ãã«ã¹ã¿ã ãã€ã³ãã䜿çšããŠãã£ãã«ããã£ãã« ã¹ã¿ãã¯ã«è¿œå ããåŸããµãŒãã¹å®è£ ã¯ã©ã¹ã®è©³çްãé©åãªå±æ§ã§æå®ããå¿ èŠããããŸãã
[DurableInstanceContext]
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class ShoppingCart : IShoppingCart
{
//âŠ
[SaveState]
public int AddItem(string item)
{
//âŠ
}
//âŠ
}
ã¯ã©ã€ã¢ã³ã ã¢ããªã±ãŒã·ã§ã³ã¯ãã«ã¹ã¿ã ãã€ã³ãã䜿çšã㊠DurableInstanceContextChannel ããã£ãã« ã¹ã¿ãã¯ã«è¿œå ããå¿ èŠããããŸãã æ§æãã¡ã€ã«å ã§ãã£ãã«ã宣èšããŠæ§æããã«ã¯ããã€ã³ãèŠçŽ ã»ã¯ã·ã§ã³ããã€ã³ãèŠçŽ æ¡åŒµã®ã³ã¬ã¯ã·ã§ã³ã«è¿œå ããå¿ èŠããããŸãã
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="durableInstanceContext"
type="Microsoft.ServiceModel.Samples.DurableInstanceContextBindingElementSection, DurableInstanceContextExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bindingElementExtensions>
</extensions>
</system.serviceModel>
ããã§ãä»ã®åºæ¬çãªãã€ã³ãèŠçŽ ãšåæ§ããã®ãã€ã³ãèŠçŽ ãã«ã¹ã¿ã ãã€ã³ãã§äœ¿çšã§ããããã«ãªããŸããã
<bindings>
<customBinding>
<binding name="TextOverHttp">
<durableInstanceContext contextType="HttpCookie"/>
<reliableSession />
<textMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
ãŸãšã
ãã®ãµã³ãã«ã§ã¯ãã«ã¹ã¿ã ãããã³ã« ãã£ãã«ãäœæããæ¹æ³ãšããããæå¹ã«ããããã«ãµãŒãã¹åäœãã«ã¹ã¿ãã€ãºããæ¹æ³ã瀺ããŸããã
æ§æã»ã¯ã·ã§ã³ã䜿çšã㊠IStorageManager å®è£
ãæå®ããããšã§ããã®æ¡åŒµæ©èœãããã«åŒ·åããããšãã§ããŸãã ããã«ããããµãŒãã¹ ã³ãŒããåã³ã³ãã€ã«ããã«ãããã³ã° ã¹ãã¢ã倿Žã§ããŸãã
ããã«ãã€ã³ã¹ã¿ã³ã¹ã®ç¶æ
ãã«ãã»ã«åããã¯ã©ã¹ (StateBag ãªã©) ãå®è£
ã§ããŸãã ãã®ã¯ã©ã¹ã«ããã倿Žããããã³ã«ç¶æ
ãä¿æãããŸãã ãã®æ¹æ³ã«ãããSaveState 屿§ã®äœ¿çšãåé¿ããªãããæ°žç¶ããåŠçãããæ£ç¢ºã«å®è¡ã§ããŸã (ããšãã°ãSaveState 屿§ãå«ãã¡ãœãããåŒã³åºããã³ã«ç¶æ
ãä¿åããã®ã§ã¯ãªããç¶æ
ãå®éã«å€æŽããããšãã«ä¿æã§ããŸã)ã
ãã®ãµã³ãã«ãå®è¡ãããšã次ã®åºåã衚瀺ãããŸãã ã¯ã©ã€ã¢ã³ãã¯ã2 ã€ã®ååãã·ã§ããã³ã° ã«ãŒãã«è¿œå ãããã®åŸã·ã§ããã³ã° ã«ãŒãã«ããååã®äžèЧããµãŒãã¹ããååŸããŸãã ã©ã¡ããã®ã³ã³ãœãŒã«ã§ Enter ããŒãæŒããšããµãŒãã¹ãšã¯ã©ã€ã¢ã³ããã©ã¡ããã·ã£ããããŠã³ãããŸãã
Enter the name of the product: apples
Enter the name of the product: bananas
Shopping cart currently contains the following items.
apples
bananas
Press ENTER to shut down client
泚
ãµãŒãã¹ãåãã«ããããšãããŒã¿ããŒã¹ ãã¡ã€ã«ãäžæžããããŸãã ãµã³ãã«ãè€æ°åå®è¡ããéã«ç¶æ ãä¿æãããŠããããšã確èªããã«ã¯ãå®è¡ã®ãã³ã«ãµã³ãã«ãåãã«ãããªãããã«ããŠãã ããã
ãµã³ãã«ãã»ããã¢ããããã«ããããã³å®è¡ããã«ã¯
Windows Communication Foundation ãµã³ãã«ã® 1 åéãã®ã»ããã¢ããã®æé ãå®è¡ããããšã確èªããŸãã
ãœãªã¥ãŒã·ã§ã³ããã«ãããã«ã¯ããWindows Communication Foundation ãµã³ãã«ã®ãã«ããã®æé ã«åŸããŸãã
åäžãŸãã¯è€æ°ã³ã³ãã¥ãŒã¿ãŒæ§æã§ãµã³ãã«ãå®è¡ããã«ã¯ããWindows Communication Foundation ãµã³ãã«ã®å®è¡ãã®æé ã«åŸããŸãã
泚
ãã®ãµã³ãã«ãå®è¡ããã«ã¯ãSQL Server 2005 ãŸã㯠SQL Express 2005 ãå®è¡ããŠããå¿ èŠããããŸãã SQL Server 2005 ãå®è¡ããŠããå Žåã¯ããµãŒãã¹ã®æ¥ç¶æååã®æ§æã倿Žããå¿ èŠããããŸã è€æ°ã³ã³ãã¥ãŒã¿ãŒã§å®è¡ããŠããå ŽåãSQL Server ãå¿ èŠãªã®ã¯ãµãŒã㌠ã³ã³ãã¥ãŒã¿ãŒã ãã§ãã