BizTalk 2010 Installation and Configuration – Disable the Shared Memory Protocol (Part 7)

BizTalk 2010 Installation and Configuration – Disable the Shared Memory Protocol (Part 7)

Under certain stress conditions (such as clients accessing SQL Server from the same computer), the SQL Server Shared Memory protocol may lower BizTalk Server performance. You can resolve this problem by disabling the use of the Shared Memory network protocol in the SQL Server Client Network Utility. To disable Shared Memory protocol for SQL Server […]

BizTalk 2010 Installation and Configuration – Install and Configure Windows SharePoint Services (Part 6)

BizTalk 2010 Installation and Configuration – Install and Configure Windows SharePoint Services (Part 6)

Windows SharePoint Services is a collection of services for Windows Server which enable you to share information, collaborate with other users on documents, and create lists and Web part pages. For information and procedures on installing Windows SharePoint Services, see Appendix A. Note You do not need to install WSS if you do not also […]

StreamInsight: Obscure LINQ error – The field ‘Key’ of type ‘IKey`1’ either contains a nested member, or is a type that is not supported as event type field

This is a pretty obscure one, and a nice short snippet of a blog post.  I ran into this error yesterday while building out some StreamInsight applications for real time web analytics, and was very briefly stumped.  Let’s have a quick peek at how I ran into it.

Starting with a working query, I needed a different pivot/aggregation on the same data stream.  My working query was:

Code Snippet
  1. // Create the "average" quality metrics for each video from raw video quality
  2. // metrics (i.e. not quantized)
  3. var videoQualityByVideo = from e in this.videoQualityStream
  4. group e by new { e.ApplicationId, e.VideoId } into videoGroups
  5. from win in videoGroups.TumblingWindow(defaultWindowSize,
  6. HoppingWindowOutputPolicy.ClipToWindowEnd)
  7. select new
  8. {
  9. ApplicationId = videoGroups.Key.ApplicationId,
  10. VideoId = videoGroups.Key.VideoId,
  11. AverageBitrate = win.Avg(e => e.BitRate)
  12. };

Pretty basic stuff – now, I wanted to group by another field (in this case a field called EdgeServerName).  So, I copy and paste, change the grouping field name and away we go:

Code Snippet
  1. // Create the "average" quality metrics for each video from raw video quality
  2. // metrics (i.e. not quantized)
  3. var videoQualityByEdgeServer = from e in this.videoQualityStream
  4. group e by new { e.EdgeServerName } into videoGroups
  5. from win in videoGroups.TumblingWindow(defaultWindowSize,
  6. HoppingWindowOutputPolicy.ClipToWindowEnd)
  7. select new
  8. {
  9. EdgeServerName = videoGroups.Key,
  10. AverageBitrate = win.Avg(e => e.BitRate)
  11. };

Should be fine – right?  Those of you familiar with LINQ are probably already laughing at the minor syntax mistake I made, but for the rest of us here’s what happened when I tried to run the query:

Microsoft.ComplexEventProcessing.Linq.QueryGenerationException was unhandled
  Message=The field 'Key' of type 'IKey`1' either contains a nested member, or is a type that 
is not supported as event type field.  Source=Microsoft.ComplexEventProcessing.Diagnostics
  StackTrace:
Microsoft.ComplexEventProcessing.Diagnostics.Exceptions.Throw(Exception exception)       
at Microsoft.ComplexEventProcessing.Linq.GroupUnionSelectRewriter.VisitMemberAccess(MemberExpression memberExpr)
...

Ouch.  What did I do wrong?  A composite group key must have more than one field!

Right Wrong! Right
Code Snippet
  1. group e by new { e.ApplicationId, e.VideoId } into videoGroups
Code Snippet
  1. group e by new { e.ApplicationId } into videoGroups
Code Snippet
  1. group e by e.ApplicationId into videoGroups

Removing the new {} syntax for a single grouping field worked perfectly.  Another bit of LINQ learned!

Code Snippet
  1. // Create the "average" quality metrics for each video from raw video quality
  2. // metrics (i.e. not quantized)
  3. var videoQualityByEdgeServer = from e in this.videoQualityStream
  4. group e by e.EdgeServerName into videoGroups
  5. from win in videoGroups.TumblingWindow(defaultWindowSize,
  6. HoppingWindowOutputPolicy.ClipToWindowEnd)
  7. select new
  8. {
  9. EdgeServerName = videoGroups.Key,
  10. AverageBitrate = win.Avg(e => e.BitRate)
  11. };

But wait there’s more!  Through the course of the same project, I also ran into another way to throw this error, in a slightly different fashion.

Code Snippet
  1. var videoQualityByEdgeServer = from e in this.videoQualityStream
  2. group e by new { e.ApplicationId, e.EdgeServerName } into edgeGroups
  3. from win in edgeGroups.TumblingWindow(videoQualityEventWindowSize, windowAlignment,
  4. HoppingWindowOutputPolicy.ClipToWindowEnd)
  5. select new
  6. {
  7. ApplicationId = edgeGroups.Key,
  8. EdgeServerName = edgeGroups.Key.EdgeServerName,
  9.  
  10. // Buffering Milliseconds -> Seconds
  11. // Divide by sampling frequency seconds
  12. // Multiply by 100 (1 / 1000 * 100 = 1 / 10)
  13. AvgBitrate = win.Avg(e => e.BitRate)
  14. };

If you have a composite key, and don’t use the individual properties of the grouping key, the error is thrown.  Easy in retrospect, right?

Windows Azure AppFabric CTP October Release

Windows Azure AppFabric CTP October Release

Today we are announcing the Windows Azure AppFabric CTP October Release, available in our LABS environment: http://portal.appfabriclabs.com.   

This release introduces an exciting new service called Windows Azure AppFabric Caching, some important new features for Service Bus, and some bug fixes for Access Control.  The Caching service is the first of several new services planned for AppFabric, several of which are being announced at PDC today. 

Taken together these new services take Windows Azure AppFabric beyond the scope of providing cloud connectivity and start to fulfill the vision of a comprehensive cloud middleware platform for developing, deploying and managing applications on the Windows Azure Platform.  You can learn more about Windows Azure AppFabric, including the new services announced today at PDC, on our new website – www.microsoft.com/appfabric/azure.

Here are the highlights of the release:

Caching: Windows Azure AppFabric Caching is a distributed, in-memory cache for applications running in Windows Azure. 

  • It can significantly speed up access to data for your Windows Azure applications.
  • It is delivered as a cloud service, so it’s simple and requires no administration on your part to setup or maintain.
  • It is based off of Windows Service AppFabric Caching capabilities, which means it is proven and uses a familiar programming model.

Service Bus: In this release we are introducing some new enhancements to the Service Bus:

  • Durable Messaging – This gives larger storage capacity, larger message size, and durable persistence to Message Buffers.
  • Load balancing – We now allow multiple listeners on the same connection point, which provides for load balancing solutions with no single point of failure.
  • Improved Management- All management operations (for both Message Buffers and Connection Points) are now explicit, the management store is persistent and management data can be accessed through Atom Publishing Protocol / REST.

Note: this release of Service Bus is focused on getting feedback in these new features and does not support the full set of features available in production today.  We will be adding all of the production features back together with the new features in a future CTP release in LABS before releasing the full updated Service Bus to production.

Access Control: This release contains only bug fixes for Access Control; no new functionality added since the LABS September Release.                                                                                                                                                 

Keep in mind that in the LABS environment there is no SLA, but accounts and usage of the services are free.  As always, we encourage you to check it out and let us know what you think of the new features.

The Windows Azure AppFabric Team

 

ASP.NET MVC 3: Layouts with Razor

ASP.NET MVC 3: Layouts with Razor

Two weeks ago we shipped the ASP.NET MVC 3 Beta Release.  It supports “go live” deployments, and includes a bunch of nice improvements/enhancements.  You can see a summary of the new ASP.NET MVC 3 features in my beta announcement post.  Also read my original ASP.NET MVC 3 Preview post to learn about other ASP.NET MVC 3 features that showed up with that initial preview release.

This is another in a series of “mini-posts” I’m doing that talk about a few of the new ASP.NET MVC 3 Beta features in more detail:

In today’s post I’m going to discuss layout pages with Razor, and discuss some of the improvements to them that we introduced with the recent ASP.NET MVC 3 Beta.

Razor Basics

ASP.NET MVC 3 ships with a new view-engine option called “Razor” (in addition to continuing to support/enhance the existing .aspx view engine).

You can learn more about Razor, why we are introducing it, and the syntax it supports from my Introducing Razor blog post.  If you haven’t read that post yet, take a few minutes and read it now (since the rest of this post will assume you have read it). Once you’ve read the Introducing Razor post, also read my ASP.NET MVC 3 Preview post and look over the ASP.NET MVC 3 Razor sample I included in it.

What are Layouts?

You typically want to maintain a consistent look and feel across all of the pages within your web-site/application.  ASP.NET 2.0 introduced the concept of “master pages” which helps enable this when using .aspx based pages or templates.  Razor also supports this concept with a feature called “layouts” – which allow you to define a common site template, and then inherit its look and feel across all the views/pages on your site.

Using Layouts with Razor

In my last blog post I walked through a simple example of how to implement a /Products URL that renders a list of product categories:

image_thumb_1263F129[1]

Below is a simple ProductsController implementation that implements the /Products URL above.  It retrieves a list of product categories from a database, and then passes them off to a view file to render an appropriate HTML response back to the browser:

image_thumb_579C4852[1]

Here is what the Index.cshtml view file (implemented using Razor) looks like:

image_thumb_17A2B20D[1]

The above view file does not yet use a layout page – which means that as we add additional URLs and pages to the site we’ll end up duplicating our core site layout in multiple places.  Using a layout will allow us to avoid this duplication and make it much easier to manage our site design going forward.  Let’s update our sample to use one now.

Refactoring to use a Layout

Razor makes it really easy to start from an existing page and refactor it to use a layout.  Let’s do that with our simple sample above.  Our first step will be to add a “SiteLayout.cshtml” file to our project under the \Views\Shared folder of our project (which is the default place where common view files/templates go):

image

SiteLayout.cshtml

We’ll use the SiteLayout.cshtml file to define the common content of our site.  Below is an example of what it might look like:

image

A couple of things to note with the above file:

  • It is no longer necessary (as of the ASP.NET MVC 3 Beta) to have an @inherits directive at the top of the file. You can optionally still have one if you want (for example: if you want a custom base class), but it isn’t required.  This helps keep the file nice and clean.  It also makes it easier to have designers and non-developers work on the file and not get confused about concepts they don’t understand.
  • We are calling the @RenderBody() method within the layout file above to indicate where we want the views based on this layout to “fill in” their core content at that location in the HTML.
  • We are outputting the “View.Title” property within the <title> element of our <head> section.  I’ll discuss how this is used in a bit.

And now we have a common layout template that we can use to maintain a consistent look and feel across any number of pages on our site.

Index.cshtml

Let’s now update our Index.cshtml view to be based on the SiteLayout.cshtml file we just created.  Below is an first-cut of what it might look like:

image

A couple of things to note about the above file:

  • We did not need to wrap our main body content within a tag or element – by default Razor will automatically treat the content of Index.cshtml as the “body” section of the layout page.  We can optionally define “named sections” if our layout has multiple replaceable regions.  But Razor makes the 90% case (where you only have a body section) super clean and simple.

  • We are programmatically setting the View.Title value within our Index.cshtml page above.  The code within our Index.cshtml file will run before the SiteLayout.cshtml code runs – and so we can write view code that programmatically sets values we want to pass to our layout to render.  This is particularly useful for things like setting the page’s title, as well as <meta> elements within the <head> for search engine optimization (SEO).

  • At the moment, we are programmatically setting the Layout template to use within our Index.cshtml page.  We can do this by setting the Layout property on the View (note: in the first preview this property was called “LayoutPage” – we changed it to just be “Layout” with the ASP.NET MVC 3 Beta).  I’ll discuss some alternative ways (new with the ASP.NET MVC 3 Beta) that we can set this property shortly.

And now when we request the /Products URL within our site, we’ll get the following HTML returned:

image

Notice above how the returned HTML content is a merge of the SiteLayout.cshtmk and Index.cshtml.  The “Product Categories” title at the top is set correctly based on the view, and our dynamic list of categories is populated in the correct place.

DRYing things up with _ViewStart

Currently we are programmatically setting the layout file to use at the top of our Index.cshtml file.  This is fine for cases where we have some view-specific logic where the layout file will vary depending on the specific view.  But setting it this way can end up being redundant and duplicative for most web applications – where either all of the views use the same layout, or if they have different layouts (for example: for mobile devices or localized sites) the logic for which layout to pick is common across all of the views.

The good news is that Razor (starting with the ASP.NET MVC 3 Beta release) includes a new feature that enables us to remove the need to explicitly set the Layout in each view – and instead allows us to define the layout logic once for all views in the site – making our view files even cleaner and more maintainable (and ensuring we keep to the DRY principle: Don’t Repeat Yourself):

image

Starting with the ASP.NET MVC 3 Beta release, you can now add a file called _ViewStart.cshtml (or _ViewStart.vbhtml for VB) underneath the \Views folder of your project:

image

The _ViewStart file can be used to define common view code that you want to execute at the start of each View’s rendering.  For example, we could write code like below within our _ViewStart.cshtml file to programmatically set the Layout property for each View to be the SiteLayout.cshtml file by default:

image

Because this code executes at the start of each View, we no longer need to explicitly set the Layout in any of our individual view files (except if we wanted to override the default value above).

Important: Because the _ViewStart.cshtml allows us to write code, we can optionally make our Layout selection logic richer than just a basic property set.  For example: we could vary the Layout template that we use depending on what type of device is accessing the site – and have a phone or tablet optimized layout for those devices, and a desktop optimized layout for PCs/Laptops.  Or if we were building a CMS system or common shared app that is used across multiple customers we could select different layouts to use depending on the customer (or their role) when accessing the site.

This enables a lot of UI flexibility.  It also allows you to more easily write view logic once, and avoid repeating it in multiple places.

Note: You can also specify layouts within a Controller or an Action Filter. So if you prefer to keep the layout selection logic there you can do that as well.

Finished Sample

Below is a screen-shot of the simple application we have been building:

image

Here is the ProductsControllers that implements the /Products URL and retrieves the categories from a database and passes them to a view template to render:

image_thumb_579C4852[1]

Here is the Index.cshtml view that we are using the render the /Products response:

image

Here is the SiteLayout.cshtml layout file we are using to implement a consistent look and feel across our site:

image

Here is the _ViewStart.cshtml file that we are using to specify that all views in our site by default use the SiteLayout.cshtml file:

image

And here is the generated HTML from the /Products URL:

image

And because we now have a common layout file for our site, we can build out more functionality, controllers and views within our application – and have a site UI experience that is both consistent and very easy to maintain.

More Advanced Stuff

Two common questions people often ask are:

1) Can I have nested layout files?

2) Can I have multiple, non-contiguous, replaceable regions within a layout file – so that I can “fill in” multiple different sections within my view files.

The answer to both of these questions is YES!  I’ll blog some samples of how to do this in the future.

Summary

As I’ve mentioned before, one of the themes we’ve focused on with the ASP.NET MVC 3 and Razor releases has been to make the code you write cleaner and more concise.  We think the new layout functionality coming with this release contributes nicely towards making view files even easier to read and write.  I’ll be covering other nice improvements like this that are new to the ASP.NET MVC 3 Beta in future posts.

Hope this helps,

Scott

P.S. In addition to blogging, I am also now using Twitter for quick updates and to share links. Follow me at: twitter.com/scottgu

Holding a Reference to the EF MetadataWorkspace for WCF Services

The title lends itself to a bit thought.  Why would the developer feel the need hold a static reference to the MetadataWorkspace of an Entity Framework (EF) model from within their WCF service-oriented applications?  The premise being that the WCF services are using EF to serve up data from a backend data store.  The answer is twofold.  Firstly, loading the EF metadata data into memory is expensive and secondly and most importantly is that EF has a depreciation policy for the metadata cache.  The deprecation policy kicks in after the predetermined threshold has been reach (typically 20 minutes of idle time) and removes the metadata from cache.  This means that the expense of loading EF metadata into memory is incurred after the idle time has been reach and the deprecation policy has been completed.  In laymen terms, the first WCF client call making use of an EF query is subject to a warm-up delay while EF loads the metadata cache.  The larger the model, the longer that ‘first’ user of the service must wait for their results.  To maintain consistent service response rates, one can hold a reference to the MetadataWorkspace object to ensure that EF doesn’t remove it from its cache.

In short, the solution submitted in this blog pertains to those applications exhibiting lengthy EF startup durations, periodic idle time with their services and a client base that expects predictable service response times.

Background

When an EntityConnection is created, the Entity Framework will load the conceptual, storage and mapping between the conceptual model and the storage model.  You can see this if you examine the CSpace (conceptual), SSpace (storage), and CSSpace (conceptual/storage mapping) item collection properties of the MetadataCache instance once the EDM has been loaded.  For example, the following code opens an EntityConnection and a QuickWatch of the MetadataWorkspace property of the connection reveals the CSpace, CSSpace, OCSpace, OSpace and SSpace collection properties.  With this model we have 274 items in the conceptual model, 314 items in the storage model and 1 item in the conceptual to storage mapping.

Note: the model was created from the AdventureWorksLT2008R2 which is included with the SQL Server 2008R2 product sample databases on codeplex.

Code Snippet
  1. using (EntityConnection connection = new EntityConnection(“Name=AdventureWorksLT2008R2Entities”))
  2. {
  3.     MetadataWorkspace workspace = connection.GetMetadataWorkspace();
  4.     CountMetaDataItems(workspace);
  5. }
 
Model      Count      
CSpace  274
OSpace 0
SSpace 314
CSSpace 1
OCSpace 0
Note that object model and mapping between the object and conceptual model is not loaded when an EntityConnection is created, the associated item collections are empty.  The CountMetaDataItems helper function was created to count the items in each collection.
 
Code Snippet
  1. public static void CountMetaDataItems(MetadataWorkspace workspace)
  2. {
  3.     ItemCollection itemCollection = null;
  4.  
  5.     // CSpace
  6.     if (workspace.TryGetItemCollection(DataSpace.CSpace, out itemCollection))
  7.         Console.WriteLine(“{0}  {1}”, DataSpace.CSpace.ToString(), itemCollection.Count);
  8.     else
  9.         Console.WriteLine(“{0}  {1}”, DataSpace.CSpace.ToString(), 0);
  10.  
  11.     // OSpace
  12.     if (workspace.TryGetItemCollection(DataSpace.OSpace, out itemCollection))
  13.         Console.WriteLine(“{0}  {1}”, DataSpace.OSpace.ToString(), itemCollection.Count);
  14.     else
  15.         Console.WriteLine(“{0}  {1}”, DataSpace.OSpace.ToString(), 0);
  16.  
  17.     // SSpace
  18.     if (workspace.TryGetItemCollection(DataSpace.SSpace, out itemCollection))
  19.         Console.WriteLine(“{0}  {1}”, DataSpace.SSpace.ToString(), itemCollection.Count);
  20.     else
  21.         Console.WriteLine(“{0}  {1}”, DataSpace.SSpace.ToString(), 0);
  22.  
  23.     // CSSpace
  24.     if (workspace.TryGetItemCollection(DataSpace.CSSpace, out itemCollection))
  25.         Console.WriteLine(“{0} {1}”, DataSpace.CSSpace.ToString(), itemCollection.Count);
  26.     else
  27.         Console.WriteLine(“{0} {1}”, DataSpace.CSSpace.ToString(), 0); ;
  28.  
  29.     // OCSpace
  30.     if (workspace.TryGetItemCollection(DataSpace.OCSpace, out itemCollection))
  31.         Console.WriteLine(“{0} {1}”, DataSpace.OCSpace.ToString(), itemCollection.Count);
  32.     else
  33.         Console.WriteLine(“{0} {1}”, DataSpace.OCSpace.ToString(), 0);
  34. }

So how do we load the object model?  The MetadataWorkspace object constructor sound promising.  It can load all the .csdl, .msl and ssdl embedded resources from the available assemblies.  Let’s give it a try.  The following code assumes that model resources are embedded into the executing assembly.  If not, the assembly fully qualified name would have to be used together with a known type to return the assembly for the model. An example of which is commented out in the code snippet below.  If your model is created in a separate assembly, then you must load the assembly using the assembly qualified name of a type within the model as shown in the lines 1-4 in the code snippet below.

Code Snippet
  1. //string assemblyQualifiedName = @”AdventureWorksModel.AdventureWorksLT2008R2Entities,” +
  2. //                   @”AdventureWorksModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”;
  3. //Type anyModelType = Type.GetType(assemblyQualifiedName);
  4. //Assembly modelAssembly = Assembly.GetAssembly(anyModelType);
  5.  
  6. Assembly modelAssembly = Assembly.GetExecutingAssembly();
  7. Assembly[] assemblys = { modelAssembly };
  8. MetadataWorkspace workspace = new MetadataWorkspace(new string[] { @”res://*/”},
  9.     new Assembly[] { Assembly.GetExecutingAssembly() });
  10. CountMetaDataItems(workspace);
 
Model      Count      
CSpace  274
OSpace 0
SSpace 314
CSSpace 1
OCSpace 0

As we can see from the output above, the object model is not loaded.  This is because the object model is loaded during view generation or during the first query referencing an entity set.  The generated views are then stored inside the object model.  So what this means is that we can load the conceptual, storage and conceptual to storage mapping into a MetadataWorkspace instance and then instantiate a new EntityConnection using this MetadataWorkspace instance.  The EntityConnection instance can then be used to in the ObjectContext constructor.  The only thing left would be to build a LINQ query which becomes converted into a command tree upon which the object model is loaded into cache.  A code sample is shown below.

Code Snippet
  1. string constr = ConfigurationManager.ConnectionStrings[“AdventureWorksDB”].ConnectionString;
  2. System.Data.Common.DbConnection dbConn = new SqlConnection(constr);
  3. EntityConnection entConn = new EntityConnection(workspace, dbConn);
  4.  
  5. using (AdventureWorksLT2008R2Entities dc = new AdventureWorksLT2008R2Entities(entConn))
  6. {
  7.     var custString = from c in dc.Customers
  8.                      select c;
  9.     CountMetaDataItems(dc.MetadataWorkspace);
  10. }
Model      Count      
CSpace  274
OSpace 39
SSpace 314
CSSpace 1
OCSpace 37
 
The output above shows that each of the models has been loaded into the workspace simply because the application reused a reference to the metadata workspace when constructing the EntityConnection.  To ensure that the Entity Framework deprecation policies do not remove the metadata from cache after a period of inactivity, hold a static reference to the workspace.  I will show this below.

WCF Services Initialization

What’s left is to initialize the EF MetadataWorkspace during startup of the WCF service and hold a static reference which can be used for subsequent EF queries.  Fortunately WCF offers a number of trivial options to perform ‘hook’ into the service startup.  Below is a list of a number of options, you can read this blog entry for a more descriptive read.  I will show a straight forward sample of initializing the MetadataWorkspace by creating custom ServiceHostFactory and ServiceHost classes and implementing the ServiceHostBase.InitializeRunTime() method.

  • Global.asmx file
    • Provides that the WCF service is in ASP.NET compatibility mode
    • Called during startup of WCF service
  • Static AppInitialize() method
    • Must be place into the App_Code folder
  • Implementing ServiceHostFactory and a custom ServiceHost
    • override the InitializeRuntime() method
  • WCF ServiceHostEvents

WCF Sample Implementation

Create a class to hold a global static reference to the MetadataWorkspace which can be globally referenced. 

Code Snippet
  1. public class GlobalWorkspace
  2. {
  3.     private static object locker = new object();
  4.     private static MetadataWorkspace workSpace = null;
  5.  
  6.     public static MetadataWorkspace WorkSpace
  7.     {
  8.         get
  9.         {
  10.             lock (locker)
  11.             {
  12.                 if (workSpace == null)
  13.                 {
  14.                     string assemblyQualifiedName = @”AdventureWorksModel.AdventureWorksLT2008R2Entities,” +
  15.                                        @”AdventureWorksModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”;
  16.                     Type anyModelType = Type.GetType(assemblyQualifiedName);
  17.                     Assembly modelAssembly = Assembly.GetAssembly(anyModelType);
  18.  
  19.                     Assembly[] assemblys = { modelAssembly };
  20.                     workSpace = new MetadataWorkspace(new string[] { @”res://*/” }, assemblys);
  21.  
  22.                     string constr = ConfigurationManager.ConnectionStrings[“AdventureWorksDB”].ConnectionString;
  23.                     System.Data.Common.DbConnection dbConn = new SqlConnection(constr);
  24.                     EntityConnection entConn = new EntityConnection(workSpace, dbConn);
  25.  
  26.                     using (AdventureWorksLT2008R2Entities dc = new AdventureWorksLT2008R2Entities(entConn))
  27.                     {
  28.                         var custString = from c in dc.Customers
  29.                                          select c;
  30.                         workSpace = dc.MetadataWorkspace;
  31.                     }
  32.                 }
  33.             }
  34.             return workSpace;
  35.         }
  36.         private set {}
  37.     }
  38. }

Create a WCF Service called AWSales.  Modify the interface to include a operational contract, for example GetCustomers(string firstName). 

Code Snippet
  1. [ServiceContract]
  2. public interface IAWSales
  3. {
  4.     [OperationContract]
  5.     IList<Customer> GetCustomers(string firstName);
  6. }

Create a custom service host by deriving from ServiceHost. 

Code Snippet
  1. public class AWSalesServiceHost : ServiceHost
  2. {
  3.     public AWSalesServiceHost(Type serviceType, params Uri[] baseAddresses)
  4.     : base(serviceType, baseAddresses) { }
  5.  
  6.     protected override void InitializeRuntime()
  7.     {
  8.         MetadataWorkspace workspace = GlobalWorkspace.WorkSpace;
  9.         base.InitializeRuntime();
  10.     }
  11. }

Create a custom ServiceHostFactory to instantiate the derived ServiceHost.

Code Snippet
  1. public class AWSalesServiceHostFactory : ServiceHostFactory
  2. {
  3.     protected override ServiceHost CreateServiceHost(Type t, Uri[] baseAddresses)
  4.     {
  5.         return new AWSalesServiceHost(typeof(AWSales), baseAddresses);
  6.     }
  7.  
  8.     public override ServiceHostBase CreateServiceHost(string service,
  9.         Uri[] baseAddresses)
  10.     {
  11.         return new AWSalesServiceHost(typeof(AWSales), baseAddresses);
  12.     }
  13. }

Implement the service contract and utilize the static reference to MetadataWorkspace when creating your EntityConnections.

Code Snippet
  1. public class AWSales : IAWSales
  2. {
  3.     public IList<Customer> GetCustomers(string firstName)
  4.     {
  5.         IList<Customer> customers = null;
  6.         string constr = ConfigurationManager.ConnectionStrings[“AdventureWorksDB”].ConnectionString;
  7.         System.Data.Common.DbConnection dbConn = new SqlConnection(constr);
  8.         EntityConnection entConn = new EntityConnection(GlobalWorkspace.WorkSpace, dbConn);
  9.  
  10.         using (AdventureWorksLT2008R2Entities dc = new AdventureWorksLT2008R2Entities(entConn))
  11.         {
  12.             customers = (from c in dc.Customers
  13.                          where c.FirstName == firstName
  14.                          select c).ToList<Customer>();
  15.         }
  16.         return customers;
  17.     }
  18. }

Set the ‘Factory’ attribute in the .svc file.

Code Snippet
  1. <% @ServiceHost Debug=”true” Factory=”WcfService.AWSalesServiceHostFactory” %>

Conclusion

The practice suggested in this blog does not pertain to all WCF services.  For those smaller or medium size EF models it doesn’t really matter if the Entity Framework deprecates the metadata cache after periods of inactivity, the model will load quite quickly and in the end, the user will never know this occurred.  But for larger models, where loading time is much longer and the experience of the end user could be impacted, the technique outlined in this blog may be worth exploring.

Behavior of BizTalk WCF Publishing Wizard When Creating Multiple Operations or Services at Once

Behavior of BizTalk WCF Publishing Wizard When Creating Multiple Operations or Services at Once

So what happens when you create a few operations or services during a single instance of the BizTalk WCF Service Publishing wizard? What types of web service projects and BizTalk messaging configurations get produced? I was messing around with this the other day, and thought I’d quickly show the output. Maybe this is common knowledge, […]