<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://community.devexpress.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>XPO</title><link>http://community.devexpress.com/blogs/xpo/default.aspx</link><description>eXpress Persistent Objects</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 SP1 (Build: 30415.43)</generator><item><title>Using SQL Server 2008 spatial data from XPO</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/08/19/using-sql-server-2008-spatial-data-from-xpo.aspx</link><pubDate>Tue, 19 Aug 2008 14:00:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:231621</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=231621</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/08/19/using-sql-server-2008-spatial-data-from-xpo.aspx#comments</comments><description>&lt;p&gt;Boris posted me some code that I used to play around with, in order to make XPO work with &lt;a href="http://msdn.microsoft.com/en-us/library/bb933876.aspx"&gt;SQL Server 2008 spatial data&lt;/a&gt;. It is possible to make it work, quite easily actually, but there are a few things that need to be considered, and where more than one solution is possible. Let&amp;#39;s see.&lt;/p&gt;
&lt;p&gt;First, we need a class to store data in the client application. This is the one I&amp;#39;m using:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;PolygonData&lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;XPObject&lt;/span&gt; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; PolygonData(&lt;span style="color:#2b91af;"&gt;Session&lt;/span&gt; session)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; : &lt;span style="color:blue;"&gt;base&lt;/span&gt;(session) { }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; name;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; Name {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; name; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; name, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;SqlGeography&lt;/span&gt; polygon;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; [&lt;span style="color:#2b91af;"&gt;ValueConverter&lt;/span&gt;(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;GeographyConverter&lt;/span&gt;))]&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; [&lt;span style="color:#2b91af;"&gt;DbType&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;geography&amp;quot;&lt;/span&gt;)]&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlGeography&lt;/span&gt; Polygon {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; polygon; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;Polygon&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; polygon, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This is already the first thing that probably needs some thought. In order to use the SqlGeography class as the property type, it is necessary to have a reference to the assembly Microsoft.SqlServer.Types. That assembly is not currently part of the .NET Framework, but it is installed together with SQL Server. As the SqlGeography class has several pieces of useful functionality (and there are other useful classes in the same assembly), it seems weird that they aren&amp;#39;t available in the &amp;quot;standard client&amp;quot;. Apparently Microsoft prepared these classes for server-side use, and obviously this makes some sense if you&amp;#39;re going to use .NET on the server in some way, but still... there are a number of blog posts out there on the topic (try searching &lt;a href="http://www.google.com/search?q=sqlgeography+client+side"&gt;SqlGeography client side&lt;/a&gt;, for instance), and &lt;a href="http://viswaug.wordpress.com/2008/05/23/using-the-sqlgeography-type-when-working-with-sql-server-2008-spatial-features/"&gt;at least one of them&lt;/a&gt; points to a future solution that involves a separate redistributable which might become available at some point. For the time being, it would probably be possible to install the assembly in question on the client manually -- but please note that I haven&amp;#39;t looked into legal issues involved with this, so be careful!&lt;/p&gt;
&lt;p&gt;If, for whatever reasons, you don&amp;#39;t want to go this way, you would have to create your own client-side class to represent the spatial information. The other approaches described in this post would still be quite similar though.&lt;/p&gt;
&lt;p&gt;Now, as you can see, the property for the Polygon in my code is decorated with two attributes. The DbType attribute makes sure that the field gets created with the correct type &amp;quot;geography&amp;quot; in SQL Server. The ValueConverter attribute is used to convert the geography into the string format needed in SQL. Here it is:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GeographyConverter&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;ValueConverter&lt;/span&gt; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;object&lt;/span&gt; ConvertFromStorageType(&lt;span style="color:blue;"&gt;object&lt;/span&gt; value) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (value &lt;span style="color:blue;"&gt;is&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlGeography&lt;/span&gt;.Parse((&lt;span style="color:blue;"&gt;string&lt;/span&gt;) value);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;else&lt;/span&gt; &lt;span style="color:blue;"&gt;return&lt;/span&gt; value;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;object&lt;/span&gt; ConvertToStorageType(&lt;span style="color:blue;"&gt;object&lt;/span&gt; value) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; value == &lt;span style="color:blue;"&gt;null&lt;/span&gt; ? &lt;span style="color:blue;"&gt;null&lt;/span&gt; : ((&lt;span style="color:#2b91af;"&gt;SqlGeography&lt;/span&gt;) value).ToString( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Type&lt;/span&gt; StorageType {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:blue;"&gt;string&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The ConvertFromStorageType function implementation is a bit weird, since it simply skips the conversion if the object that&amp;#39;s getting passed in is not a string. This is perhaps not the most secure way of implementing this, but it&amp;#39;s good enough for the purpose of the demo. The reason I&amp;#39;m expecting objects that might not be strings is explained further down and it has to do with performance -- depending on the decision you make at that point, you might implement this function in slightly different ways.&lt;/p&gt;
&lt;p&gt;To create a bit test data, I&amp;#39;m using the following helper function in my code (the SqlGeographyBuilder is another class from Microsoft.SqlServer.Types):&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlGeography&lt;/span&gt; CreatePolygon( ) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;SqlGeographyBuilder&lt;/span&gt; builder = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlGeographyBuilder&lt;/span&gt;( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.SetSrid(4326); &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.BeginGeography(&lt;span style="color:#2b91af;"&gt;OpenGisGeographyType&lt;/span&gt;.Polygon);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.BeginFigure(55.36728, -2.74941);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.AddLine(55.40002, -2.68289);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.AddLine(55.39908, -2.74913);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.AddLine(55.36728, -2.74941);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.EndFigure( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; builder.EndGeography( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; builder.ConstructedGeography;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;With this in place, I can create and store some data:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt; uow = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt;( )) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;PolygonData&lt;/span&gt;(uow) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Name = &lt;span style="color:#a31515;"&gt;&amp;quot;Test 1&amp;quot;&lt;/span&gt;,&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Polygon = CreatePolygon( )&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }.Save( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uow.CommitChanges( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you are following along and you&amp;#39;ve built your own sample with these code snippets, you will be able to execute the sample at this point. It will get a table created in SQL Server and the spatial data inserted. Wonderful!&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://community.devexpress.com/blogs/xpo/spatialresults.png" width="400" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, of course we want to read data back from the database. In my sample, I&amp;#39;m using this simple piece of code to do it:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt; uow = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt;( )) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;var&lt;/span&gt; polygons = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;XPCollection&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;PolygonData&lt;/span&gt;&amp;gt;( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;var&lt;/span&gt; polygon &lt;span style="color:blue;"&gt;in&lt;/span&gt; polygons) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(polygon.Name);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(polygon.Polygon);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you try to run this, you will see an exception though. The reason for that is that there are types here which don&amp;#39;t match up. The SQL Server client library, somewhat confusingly, returns an object that is actually of type SqlGeography, whereas our type converter defines a storage type of string ins StorageType property. As a result, a function called ReformatReadValue is called on the connection provider we&amp;#39;re using (MSSqlConnectionProvider by default), and that function attempts to use the .NET Framework standard Convert.ChangeType function to convert a SqlGeography into a string. That function in turn expects the object to implement IConvertable, and throws an exception because it doesn&amp;#39;t do that. Phew.&lt;/p&gt;
&lt;p&gt;So what&amp;#39;s the solution to this problem? Well, making the ReformatReadValue function do the conversion of SqlGeography into string, that&amp;#39;s one solution. Let&amp;#39;s derive a connection provider and override that function:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GISProvider&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;MSSqlConnectionProvider&lt;/span&gt; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; GISProvider(&lt;span style="color:#2b91af;"&gt;IDbConnection&lt;/span&gt; connection, &lt;span style="color:#2b91af;"&gt;AutoCreateOption&lt;/span&gt; autoCreateOption)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; : &lt;span style="color:blue;"&gt;base&lt;/span&gt;(connection, autoCreateOption) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;protected&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;object&lt;/span&gt; ReformatReadValue(&lt;span style="color:blue;"&gt;object&lt;/span&gt; value, &lt;span style="color:#2b91af;"&gt;ReformatReadValueArgs&lt;/span&gt; args) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (value != &lt;span style="color:blue;"&gt;null&lt;/span&gt;) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Type&lt;/span&gt; valueType = value.GetType( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (valueType == &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;SqlGeography&lt;/span&gt;) || valueType == &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;SqlGeometry&lt;/span&gt;))&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; value.ToString( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;base&lt;/span&gt;.ReformatReadValue(value, args);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now we need to make sure this is the provider we&amp;#39;re using, instead of the standard MSSqlConnectionProvider. We can do this with an initialization line like this:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;XpoDefault&lt;/span&gt;.DataLayer =&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SimpleDataLayer&lt;/span&gt;(&lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;GISProvider&lt;/span&gt;(&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlConnection&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;data source=.;integrated security=SSPI;initial catalog=XPOSql2008Spatial&amp;quot;&lt;/span&gt;), &lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;AutoCreateOption&lt;/span&gt;.DatabaseAndSchema));&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;#39;re following along, try running your application again, with the reading code in place, and you should see the geography information read back to the client and shown on the console.&lt;/p&gt;
&lt;p&gt;There&amp;#39;s one problem with this code, and I&amp;#39;m sure you have noticed already: we are getting back a SqlGeography instance from the database client code, and this gets passed in to the ReformatReadValue method in the XPO infrastructure. There it is converted into a string. Then it gets passed into the configured value converter for the Polygon property, and gets converted in a SqlGeography instance. Sounds suboptimal, doesn&amp;#39;t it? Yeah...&lt;/p&gt;
&lt;p&gt;There is a solution to this, but it&amp;#39;s not entirely perfect. It is possible to simply ignore what ReformatReadValue wants us to do and just not convert the object (leave off the ToString() from the value the method returns). Then the SqlGeography type object will be passed in to the value converter, which needs to be implemented to ignore the fact that this is not really a string it receives. Remember, I already pointed this out above - if you want to go this &amp;quot;better performance&amp;quot; way, your value converter will have to be able to deal with the fact that it might receive objects to convert that have actually already been converted.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m only describing this solution instead of showing the code, because it&amp;#39;s not really something I want to recommend. This solution neglects the contracts of the XPO infrastructure, and that is of course a bad thing when changes are made in the future. It might also be a problem if the data has to be serialized after being read from the database - having it in string format is what XPO normally assumes, and that works well with all types of serialization. I haven&amp;#39;t made any real tests, so I can just say I don&amp;#39;t know precisely what will happen if SqlGeography instances are sent across the wire using Remoting, XML Web Services, WCF or other frameworks. So - if you&amp;#39;re interested in the performance gain, Remoting and so on are perhaps not a concern of yours (it seems unlikely anyway that Remoting and the perf gain from a few saved string conversions are *both* important to you), then it shouldn&amp;#39;t be hard to use this approach I described. Please note though that you should take extra care to have relevant unit tests in place, so that changes in future XPO versions don&amp;#39;t catch you out.&lt;/p&gt;
&lt;p&gt;Overall it seems a bit weird the way this feature has been implemented. The client side seems to convert the spatial data into the original type automatically, pretty much whether you want it or not - at least that&amp;#39;s how I understand it at this point. Since I push in string data through SQL in order to store the information, it would seem logical to be able to retrieve the string data only, and make my own decision about converting it back into object data, and specifically about the right point in time to do this. Perhaps it fits in somehow with Microsoft&amp;#39;s decision not to make Microsoft.SqlServer.Types available in the client by default. Or perhaps there&amp;#39;s something I missing right now in this regard :-)&lt;/p&gt;
&lt;p&gt;Anyway, have fun! Here&amp;#39;s the complete code of the sample I created: &lt;a href="http://community.devexpress.com/blogs/xpo/XPOSql2008Spatial.zip"&gt;XPOSql2008Spatial.zip&lt;/a&gt; (4201 bytes)&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=231621" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO and FILESTREAM - update</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/08/15/xpo-and-filestream-update.aspx</link><pubDate>Fri, 15 Aug 2008 10:40:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:231270</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=231270</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/08/15/xpo-and-filestream-update.aspx#comments</comments><description>&lt;p&gt;Yesterday I wrote about &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2008/08/14/xpo-and-sql-server-2008-filestream-support.aspx"&gt;using the new SQL Server 2008 FILESTREAM feature with XPO&lt;/a&gt;, and this morning Boris from our XPO team sent me an IM going &amp;quot;na na na, I found an easier way to do this&amp;quot;. Okay, maybe he didn&amp;#39;t quite put it like that :-) Anyway, here&amp;#39;s the code he sent me:&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt; : &lt;span style="color:#2b91af;"&gt;XPObject&lt;/span&gt; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; Something(&lt;span style="color:#2b91af;"&gt;Session&lt;/span&gt; session)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; : &lt;span style="color:blue;"&gt;base&lt;/span&gt;(session) { }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; AfterConstruction( ) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;base&lt;/span&gt;.AfterConstruction( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; streamId = &lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt;.NewGuid( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; strVal;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; StrVal {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; strVal; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;StrVal&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; strVal, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] streamData;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; [&lt;span style="color:#2b91af;"&gt;DbType&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;VARBINARY(MAX) FILESTREAM&amp;quot;&lt;/span&gt;)]&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] StreamData {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; streamData; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;StreamData&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; streamData, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt; streamId;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; [&lt;span style="color:#2b91af;"&gt;DbType&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;uniqueidentifier ROWGUIDCOL UNIQUE NOT&amp;quot;&lt;/span&gt;)]&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt; StreamId {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; streamId; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;StreamId&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; streamId, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This code removes the need for any separate structural updates, which is of course very convenient. Now, in my previous post I had already mentioned I&amp;#39;d been playing with ways of using the DbTypeAttribute, and my solution had looked almost exactly the same - only I hadn&amp;#39;t been aware that the UNIQUE keyword could be used in that precise way, and so I wasn&amp;#39;t able to get the necessary index created on the ROWGUIDCOL field. Boris&amp;#39; code takes care of that now.&lt;/p&gt;
&lt;p&gt;Is this preferable? I&amp;#39;m not entirely sure. I had one other reason to decide not to post my own similar code in my previous article, and that was the fact that the DbType parameter for the StreamId field looks very much like SQL injection. As you can see, it ends in &amp;quot;NOT&amp;quot;, and that is to combine with the &amp;quot;NULL&amp;quot; that XPO inserts into the SQL code anyway, so the field ends up being &amp;quot;NOT NULL&amp;quot;. Hm... I guess this is SQL injection, seeing how the text from the DbType is inserted into the DML code without any checks. Then again, that&amp;#39;s the exact point of having a DbType attribute in the first place - the ability to use types that XPO isn&amp;#39;t aware of - and of course it&amp;#39;s compile time data that is injected. In the end, that code has the same effect as the other code I published previously. It is important to point out that while this may look similar to code used for SQL injection attacks, it&amp;#39;s quite a different thing really, and there doesn&amp;#39;t seem to be a way of exploiting this at runtime.&lt;/p&gt;
&lt;p&gt;So is it preferable? I don&amp;#39;t know - I guess it&amp;#39;s more convenient to use in some cases. It&amp;#39;s also less dynamic. With the code I published previously, it would be possible for the initialization code to determine whether SQL Server 2008 is being used, and to make the necessary changes only if it is. By decorating the field with the DbType attribute, the class can only be used with SQL Server 2008. I guess in the end everybody will have to decide for themselves.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; Another idea from one of our untiring XPO team members - Alex this time - you could use an XPCustomObject and establish a Guid type primary key. This will be marked with ROWGUIDCOL automatically (we introduced this originally to make the databases replication friendly) and of course it will have the required unique index. I actually had a similar idea early on, but I wasn&amp;#39;t going to do this because I didn&amp;#39;t want to mix the requirements of the FILESTREAM feature with other structure... Of course you&amp;#39;ll still have to get the FILESTREAM type set correctly and using DbType on that one still makes your structure specific to SQL Server 2008. I guess my own overall decision might still be to make the modifications through SQL/DML statements, but of course (as Alex also pointed out) I should pay attention whether my table has a Guid type primary key perhaps - in which case SQL Server will not let me establish a second column with the ROWGUIDCOL attribute set.&lt;/p&gt;
&lt;p&gt;Finally, &lt;a href="http://forums/p/67872/231221.aspx#231221"&gt;I was asked to show how initialization code can be used in the context of an XAF application&lt;/a&gt;. That&amp;#39;s actually very simple, since XAF has its own mechanism of updating database structure and content with new versions of applications. That mechanism can easily be used to call some structure modification code. &lt;a href="http://www.devexpress.com/Help/Content.aspx?help=ExpressApp&amp;amp;document=CustomDocument2795.htm"&gt;It&amp;#39;s documented in the XAF help here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=231270" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO and SQL Server 2008 FILESTREAM support</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/08/14/xpo-and-sql-server-2008-filestream-support.aspx</link><pubDate>Thu, 14 Aug 2008 16:48:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:231202</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=231202</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/08/14/xpo-and-sql-server-2008-filestream-support.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://forums/p/67872/231168.aspx#231168"&gt;a recent forum post&lt;/a&gt;, Reinhold Erlacher asked me whether we supported the new FILESTREAM feature in SQL Server 2008 yet. I was not familiar with the feature, not being a SQL Server expert really, but I decided to have a look.&lt;/p&gt;
&lt;p&gt;First, I had to set up SQL Server to actually support the feature in question. A well documented process, but a bit weird nonetheless - why do they introduce features that are only available after jumping through so many additional hoops? Ah well... &lt;a href="http://msdn.microsoft.com/en-us/library/bb933995.aspx"&gt;Here are the instructions on MSDN&lt;/a&gt; - there&amp;#39;s a lot of confusing information around in blogs, apparently from pre-release versions of SQL Server 2008, so be sure to use these to get it to work with your database.&lt;/p&gt;
&lt;p&gt;Now, first I played around a bit to try and get XPO to create a database structure automatically that would be compatible with the FILESTREAM feature. That is not currently possible, as it turns out, since there are a few requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The database must have a file group for the file streams&lt;/li&gt;
&lt;li&gt;A table that has associated file streams must also have a column marked ROWGUIDCOL&lt;/li&gt;
&lt;li&gt;The ROWGUIDCOL column must have a unique index applied&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, of course, the blob column that will store the stream data must be marked FILESTREAM. We don&amp;#39;t support any of these things directly - i.e. through a built-in feature - in XPO, and I don&amp;#39;t think it&amp;#39;s likely that we will. Fortunately, it&amp;#39;s quite easy to make the necessary changes either manually (configuring the file group in SQL Server Management Studio) or automatically (using a bit of SQL code that&amp;#39;s executed after the default schema creation process from the XPO application). The process shouldn&amp;#39;t be hard to integrate with a typical deployment scenario, and of course we can&amp;#39;t help the fact that Microsoft have made it quite hard to benefit from the new feature.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m using this basic persistent class for my demo:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt;: &lt;span style="color:#2b91af;"&gt;XPObject&lt;/span&gt; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; Something(&lt;span style="color:#2b91af;"&gt;Session&lt;/span&gt; session)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; : &lt;span style="color:blue;"&gt;base&lt;/span&gt;(session) { }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;override&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; AfterConstruction( ) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;base&lt;/span&gt;.AfterConstruction( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; streamId = &lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt;.NewGuid( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; strVal;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; StrVal {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; strVal; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;StrVal&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; strVal, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] streamData;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;byte&lt;/span&gt;[] StreamData {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; streamData; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;StreamData&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; streamData, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt; streamId;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Guid&lt;/span&gt; StreamId {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;get&lt;/span&gt; { &lt;span style="color:blue;"&gt;return&lt;/span&gt; streamId; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;set&lt;/span&gt; { SetPropertyValue(&lt;span style="color:#a31515;"&gt;&amp;quot;StreamId&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;ref&lt;/span&gt; streamId, &lt;span style="color:blue;"&gt;value&lt;/span&gt;); }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I experimented briefly with the DbTypeAttribute and I had some success with it, but since custom SQL code was still required, I decided to make all relevant changes in one place instead of spreading them out. My test application is this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="font-family:Consolas;font-size:11pt;color:black;background:white;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Program&lt;/span&gt; {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color:blue;"&gt;string&lt;/span&gt;[] args) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;XpoDefault&lt;/span&gt;.DataLayer = &lt;span style="color:#2b91af;"&gt;XpoDefault&lt;/span&gt;.GetDataLayer(&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;MSSqlConnectionProvider&lt;/span&gt;.GetConnectionString(&lt;span style="color:#a31515;"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515;"&gt;&amp;quot;XPOFileStream&amp;quot;&lt;/span&gt;),&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;AutoCreateOption&lt;/span&gt;.DatabaseAndSchema);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// This sets up the DB structure. Of course we would only do this &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// once in a real app. Since we&amp;#39;re boring in this sample, we&amp;#39;re just&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// going to kill the db and go from scratch.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt; uow = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt;( )) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uow.ClearDatabase( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; CreateDBStructure( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// Create some test data&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt; uow = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt;( )) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt; something = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt;(uow);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; something.StrVal = &lt;span style="color:#a31515;"&gt;&amp;quot;Entry&amp;quot;&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; something.StreamData = &lt;span style="color:#2b91af;"&gt;UTF8Encoding&lt;/span&gt;.Default.GetBytes(&lt;span style="color:#a31515;"&gt;&amp;quot;Stuff in my stream&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uow.CommitChanges( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// Read the object back and show the stream data&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt; uow = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt;( )) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt; something = uow.FindObject&amp;lt;&lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt;&amp;gt;(&lt;span style="color:blue;"&gt;null&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Stream says: &amp;quot;&lt;/span&gt; + &lt;span style="color:#2b91af;"&gt;UTF8Encoding&lt;/span&gt;.Default.GetString(something.StreamData));&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;private&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; CreateDBStructure( ) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// Get the basic db structure created&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt; uow = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;UnitOfWork&lt;/span&gt;( )) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; uow.UpdateSchema(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;Something&lt;/span&gt;));&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:green;"&gt;// Apply schema modifications&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; execute = CommandExecutor(&lt;span style="color:#2b91af;"&gt;XpoDefault&lt;/span&gt;.DataLayer.Connection);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; execute(&lt;span style="color:#a31515;"&gt;&amp;quot;alter table Something alter column StreamId uniqueidentifier not null&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; execute(&lt;span style="color:#a31515;"&gt;&amp;quot;alter table Something alter column StreamId add rowguidcol&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; execute(&lt;span style="color:#a31515;"&gt;&amp;quot;alter table Something add constraint streamid_unique unique(StreamId)&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; execute(&lt;span style="color:#a31515;"&gt;&amp;quot;alter table Something drop column StreamData&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; execute(&lt;span style="color:#a31515;"&gt;&amp;quot;alter table Something add StreamData varbinary(max) FILESTREAM&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt; CommandExecutor(&lt;span style="color:#2b91af;"&gt;IDbConnection&lt;/span&gt; connection) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;delegate&lt;/span&gt;(&lt;span style="color:blue;"&gt;string&lt;/span&gt; command) {&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color:#2b91af;"&gt;SqlCommand&lt;/span&gt; sqlCommand = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlCommand&lt;/span&gt;(command, (&lt;span style="color:#2b91af;"&gt;SqlConnection&lt;/span&gt;) connection);&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sqlCommand.ExecuteNonQuery( );&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; };&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp; }&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can download the complete sample from here (VS 2008 SP1): &lt;a href="http://community.devexpress.com/blogs/xpo/XPOSQL2008FileStream.zip"&gt;XPOSQL2008FileStream.zip&lt;/a&gt; (4267 bytes)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: If you try to run the sample out of the box, you will be in trouble because the database is not configured to support file streams! You should therefore create a database called &amp;quot;XPOFileStream&amp;quot; manually and set it up to support file streams correctly (again, &lt;a href="http://msdn.microsoft.com/en-us/library/bb933995.aspx"&gt;as described here&lt;/a&gt;), and then run the sample.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=231202" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO Publication Service and XAF</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/08/14/xpo-publication-service-and-xaf.aspx</link><pubDate>Thu, 14 Aug 2008 10:57:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:231132</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=231132</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/08/14/xpo-publication-service-and-xaf.aspx#comments</comments><description>&lt;p&gt;I was involved in some debugging action this morning, regarding my &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2008/05/31/xpo-publication-service-update-for-8-1-4.aspx"&gt;XPO Publication Service&lt;/a&gt;. Please read &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2008/05/31/xpo-publication-service-update-for-8-1-4.aspx"&gt;this post&lt;/a&gt; (and others linked from there) to find out the basics about that service.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://www.devexpress.com/issue=Q181274"&gt;problem in question&lt;/a&gt; was that a customer was receiving a weird Remoting exception when trying to connect to a data store published through the publication service. The first test I did was to change the dependencies in the service to 8.2, build it, and run my functional tests on it - all of those worked fine.&lt;/p&gt;
&lt;p&gt;So I set out to create a simple client that would attach itself to a data store published through the Publication Service. At this point, I think a little excursion would be good. I have noticed that many people have the weirdest ideas of how to connect to a published service from XPO. Often they involve a line like this:&lt;/p&gt;
&lt;pre&gt;IDataStore dataStore = (IDataStore)Activator.GetObject(typeof(IDataStore), 
  @&amp;quot;http://tcp:2635/something.rem&amp;quot;);
&lt;/pre&gt;
&lt;p&gt;Now, this is not wrong, but it&amp;#39;s also not necessary. Retrieving a reference from the Activator is one way of interfacing with the .NET Remoting infrastructure on the client side. But - that code is already contained in the XPO libraries, so all the gory details of using Remoting are hidden. You can easily use XPO to get a connection provider (= data store) created directly, like this:&lt;/p&gt;
&lt;pre&gt;XpoDefault.GetConnectionProvider(&amp;quot;tcp://localhost:9999/something.rem&amp;quot;, 
  AutoCreateOption.DatabaseAndSchema)
&lt;/pre&gt;
&lt;p&gt;Or, even better, you can get a data layer set up directly, like this:&lt;/p&gt;
&lt;pre&gt;XpoDefault.DataLayer = XpoDefault.GetDataLayer(&amp;quot;tcp://localhost:9999/something.rem&amp;quot;, 
  AutoCreateOption.DatabaseAndSchema);&lt;/pre&gt;
&lt;p&gt;What this means is really that a connection URL for a data store published through Remoting can be used in very similar places to any other connection string. XPO will figure it out for you.&lt;/p&gt;
&lt;p&gt;On a related note, guess how to set up an XAF application to connect to a data store publication? That&amp;#39;s right, just use the URL as a connection string. For instance, put this into your app.config:&lt;/p&gt;
&lt;pre&gt;&amp;lt;add name=&amp;quot;ConnectionString&amp;quot; connectionString=&amp;quot;tcp://localhost:9999/something.rem&amp;quot; /&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Right, end of excursion. Now, I&amp;#39;d created that little client app and, in contrast to all the lines above, I was using HTTP, not TCP, for the connection. The publications.xml file for the Publication Service had this Channels section:&lt;/p&gt;
&lt;pre&gt;&amp;lt;Channels&amp;gt;
  &amp;lt;xpopub:HTTPTargetChannel&amp;gt;
    &amp;lt;Port&amp;gt;9999&amp;lt;/Port&amp;gt;
  &amp;lt;/xpopub:HTTPTargetChannel&amp;gt;
&amp;lt;/Channels&amp;gt;
&lt;/pre&gt;
&lt;p&gt;I was quite surprised to find this, but I got the same Remoting exception as described in &lt;a href="http://www.devexpress.com/issue=Q181274"&gt;the support center issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One idea I quickly had was that the problem might be related to that other weird issue I had encountered at some point when using HTTP for a publication. That issue is described in this post on my personal blog, and it&amp;#39;s certainly not irrelevant if you use Remoting or some other protocol to publish things through HTTP. So go to &lt;a href="http://www.sturmnet.org/blog/archives/2008/02/08/net-3-the-game-challenge-at-vbug-newcastle/"&gt;this article&lt;/a&gt; and have a look if you&amp;#39;re interested.&lt;/p&gt;
&lt;p&gt;Anyway, that wasn&amp;#39;t it, since the error messages were different. Nevertheless, I was able to solve the problem by switching to TCP. Probably a good idea anyway, unless you specifically need to use HTTP for firewall reasons (though it will forever remain a mystery to me why people don&amp;#39;t have a problem tunneling unknown content through HTTP, while being scared $$(*&amp;amp;less by the same data on a different port). So I changed my publications.xml to this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;Channels&amp;gt;
  &amp;lt;xpopub:TCPTargetChannel&amp;gt;
    &amp;lt;Port&amp;gt;9999&amp;lt;/Port&amp;gt;
  &amp;lt;/xpopub:TCPTargetChannel&amp;gt;
&amp;lt;/Channels&amp;gt;
&lt;/pre&gt;
&lt;p&gt;I changed all the URLs I was using to tcp://, as shown in the code lines above, and then it worked. Great. A quick test with the more complex XAF Main Demo application showed that this worked as well. Fine.&lt;/p&gt;
&lt;p&gt;So, back to the &amp;quot;why&amp;quot;... why is everything fine with TCP, but not with HTTP? Well, the answer came to me after some discussion with our support guy Dennis: the serialization formats don&amp;#39;t match. Yeah. Let me say that again - the serialization formats don&amp;#39;t match. Why doesn&amp;#39;t Remoting throw a TheSerializationFormatsDontMatchException? I don&amp;#39;t know. Anyway, that&amp;#39;s what&amp;#39;s happening.&lt;/p&gt;
&lt;p&gt;The XPO Publication Service defaults to binary encoding, even for the HTTP channel. There&amp;#39;s a property called UseBinaryEncoding on the channel, which can be changed through the config file, but it defaults to true. The XPO library, on the other hand, defaults to SOAP encoding when an HTTP channel is used. So, back to the publications.xml with the HTTPTargetChannel, and then insert this line before the code that establishes the connection to the server:&lt;/p&gt;
&lt;pre&gt;ChannelServices.RegisterChannel(new HttpChannel(null, 
  new BinaryClientFormatterSinkProvider(), null), false);
&lt;/pre&gt;
&lt;p&gt;Credit for this line goes to Dennis - he had found out that this makes things work, though he wasn&amp;#39;t exactly sure why. Here&amp;#39;s why: because the HTTP Channel is configured to use binary encoding and thereby becomes compatible with the way the Publication Service works. The XPO library doesn&amp;#39;t register the HTTP Channel again, since it&amp;#39;s already there, and it doesn&amp;#39;t change the registration either. Fine.&lt;/p&gt;
&lt;p&gt;Now, several questions come up here. First, why are the Publication Service and the XPO defaults incompatible? I don&amp;#39;t know. It&amp;#39;s certainly weird and I suspect we changed something at some point, on one or both ends. It&amp;#39;s been a long time since I wrote the Publication Service and being a pet project, it&amp;#39;s perhaps not tested well enough - still, since we&amp;#39;re talking about default settings here, it seems that this could have been found earlier if it had been like that forever. I don&amp;#39;t know.&lt;/p&gt;
&lt;p&gt;Second, is it possible to use SOAP encoding? Yes and no, oddly enough - another point where I&amp;#39;m not sure where a problem comes from. It is easy to switch the Publication Service to using SOAP, like this:&lt;/p&gt;
&lt;pre&gt;&amp;lt;Channels&amp;gt;
  &amp;lt;xpopub:HTTPTargetChannel&amp;gt;
    &amp;lt;Port&amp;gt;9999&amp;lt;/Port&amp;gt;
    &amp;lt;UseBinaryEncoding&amp;gt;false&amp;lt;/UseBinaryEncoding&amp;gt;
  &amp;lt;/xpopub:HTTPTargetChannel&amp;gt;
&amp;lt;/Channels&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The problem is, when I tried this, I got another weird exception coming up, saying that the SOAP formatter isn&amp;#39;t able to deal with generic classes being serialized. Okay then... hm. The point where we changed XPO to have generic classes involved in the inheritance hierarchy is a really long time ago, so it&amp;#39;s probably been like that since then. Interestingly, while I don&amp;#39;t know how many people use Remoting with HTTP/SOAP, I&amp;#39;m pretty sure there are some people using XML Web Services, which use HTTP/SOAP as well. The answer to that is that the SOAP formatter for Remoting isn&amp;#39;t the same as the one for XML Web Services. And they are both different from the one being used for WCF, if I&amp;#39;m not completely mistaken. Trust Microsoft to find ways of making complex things more confusing.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Summary of all the odd stuff above&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;ve stopped reading my ramblings a while ago, here&amp;#39;s the summary of important points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The reason for &lt;a href="http://www.devexpress.com/issue=Q181274"&gt;the issue&lt;/a&gt; is that the XPO Publication Service and the Remoting client code in the XPO libraries use different formatter defaults for the HTTP channel. We should look into making some changes so this would be compatible automatically.&lt;/li&gt;
&lt;li&gt;Using TCP instead of HTTP makes things work. This is probably the best idea for many cases, unless HTTP is absolutely required.&lt;/li&gt;
&lt;li&gt;Using binary formatting with HTTP also makes things work. An additional line of code is required for this purpose, but inserting this into application initialization code shouldn&amp;#39;t be a problem in most cases.&lt;/li&gt;
&lt;li&gt;Using SOAP formatting with the Publication Service is easy, but it doesn&amp;#39;t actually work for technical reasons in the Remoting SOAP formatter. We might look into this in a bit more detail to see if there&amp;#39;s anything we can do about this.&lt;/li&gt;
&lt;li&gt;Using the HTTP/SOAP combination is perfectly possible with XML Web Services as well as WCF, to my knowledge. XML Web Services are not self-hosting, so they can&amp;#39;t really be supported by the XPO Publication Service. WCF can be self-hosting and it would be possible to extend the Publication Service to support it directly. The Publication Service can be extended externally, i.e. without changes to its own code base. With or without support in the Publication Service, there are plenty of articles on this blog that show how to tunnel through Web Services and WCF.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve talked to the XPO team, and they have tracked down the problem with the SOAP formatter. Turns out this should actually work - so we regard it a bug and it will be fixed. Hang on... just now an IM tells me that the fix has been checked in internally. Will be in the next minor release.&lt;/p&gt;
&lt;p&gt;The thing with the default behavior of the XPO Remoting code is that it uses defaults the .NET Framework provides, which is a good thing of course. I guess it would make sense to change the default for the Publication Service to use SOAP instead of binary... I&amp;#39;ll probably do that soon.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=231132" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XAF/default.aspx">XAF</category></item><item><title>ANN: DXCore XPO plugin 1.2.0.1</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/08/07/ann-dxcore-xpo-plugin-1-2-0-1.aspx</link><pubDate>Thu, 07 Aug 2008 13:34:05 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:230324</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>29</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=230324</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/08/07/ann-dxcore-xpo-plugin-1-2-0-1.aspx#comments</comments><description>&lt;p&gt;Version 1.2.0.1 of the XPO plugin is now available, compiled against DXCore 3.0.8. Please download it here:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://community.devexpress.com/blogs/xpo/CR_XPOFieldSync-1.2.0.1.zip"&gt;CR_XPOFieldSync-1.2.0.1.zip&lt;/a&gt; (20489 bytes)&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;As always, if you&amp;#39;re not familiar with the purpose of the XPO plugin, please read &lt;a href="http://www.devexpress.com/Products/NET/ORM/SimplifiedCriteriaSyntax.xml"&gt;this description of the &amp;quot;Simplified Criteria Syntax&amp;quot; feature&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have recently mentioned to a few of you, through the Support Center, that I was considering retiring the plugin soon. LINQ has been mentioned several times as the query technology of choice, and I would like to make that point again. The &amp;quot;Simplified Criteria Syntax&amp;quot; feature in XPO was originally introduced as a way to write queries more easily, and specifically with the fact in mind that LINQ was at that time still about two years away from general availability. Now that LINQ is available and well supported in XPO, we do recommend you use it to write queries in code. Since LINQ is a very general-purpose technology, there will be cases where our own criteria system can do things that can&amp;#39;t be represented in a LINQ expression. But for the vast majority of cases, there&amp;#39;s no better way of writing queries in code today.&lt;/p&gt;
&lt;p&gt;Nevertheless I&amp;#39;ve changed my mind about deprecating the XPO plugin. The reason is that I&amp;#39;ve learned how many other things, apart from querying, users do with the plugin and the code it creates. Generally speaking, having a reference to a certain field in a persistent class - which is what the XPO plugin creates - is very useful in a variety of cases that don&amp;#39;t have to do directly with querying, and so cannot be covered by LINQ. So for now, I will keep supporting the XPO plugin as well as time allows.&lt;/p&gt;
&lt;p&gt;For version 1.2.x, I have restructured certain things about the way the plugin works. In prior versions, the plugin was trying to be rather clever about the code generation/modification process, for instance by removing only those elements that weren&amp;#39;t needed anymore after a code change, or inserting only those that were new. This has proved extremely tricky over time with regard to the interaction with the DXCore and the code parsing it does, since the plugin needs to know exactly what the current state of the code is while it executes several deletions and insertions, and the developer possibly keeps on typing and making more changes. The major structural change in this version is that the plugin always creates the entire code block and either inserts it or replaces the previous version with it. This does come with its own problems - see below -, but it makes things much more predictable and less dependent on details of the inner workings of the DXCore.&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a summary list of changes in this version:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Restructured lots of the plugin to solve some long-standing problems&lt;/li&gt;

  &lt;li&gt;Manual execution of sync is now possible - configure a key binding for the SyncXPOClass action&lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Fixed B95475 - (a part of the) Fields class wasn&amp;#39;t being created&lt;/li&gt;

  &lt;li&gt;Fixed B93229 - certain persistent property types weren&amp;#39;t recognized correctly&lt;/li&gt;

  &lt;li&gt;Fixed a problem where the code region was created in the wrong place, or not at all, when using nested persistent classes&lt;/li&gt;

  &lt;li&gt;Fixed CB56295 - handling of NonPersistent on base classes&lt;/li&gt;

  &lt;li&gt;Implemented CS49600 - optional inclusion of NonPersistent members - see option dialog&lt;br /&gt;&lt;/li&gt;

  &lt;li&gt;Implemented AS13477 - toggle automatic sync using a key binding - configure a key binding to the ToggleXPOAutoSync action&lt;/li&gt;

  &lt;li&gt;The &amp;quot;Global Off&amp;quot; option has been replaced by the &amp;quot;Automatic Sync&amp;quot; option, which is Off by default&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note the last entry, please. If you like to use automatic synchronization, you have to go to the options dialog after installation of the latest version and switch it on. By default, the plugin doesn&amp;#39;t use automatic sync anymore. From my own experience during testing, the manual sync is quite comfortable, although of course there&amp;#39;s a risk of forgetting to sync.&lt;/p&gt;
&lt;p&gt;There are currently three known problems with this plugin version:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The forever outstanding issue &lt;a href="http://www.devexpress.com/issue=CB8627"&gt;CB8627&lt;/a&gt;. Unfortunately, I still don&amp;#39;t have a solution to this. The DXCore parser is apparently unable to tell me if there&amp;#39;s a critical structural problem in the source code I&amp;#39;m looking at, and so the sync process creates code in the wrong place, or doesn&amp;#39;t recognize that there&amp;#39;s already a region it should replace. I&amp;#39;m still hoping to be able to fix this problem eventually. In this version, one possible workaround is to use manual sync - just make sure your project is valid (hit Shift-Ctrl-B to build, for instance) and if that&amp;#39;s all fine, trigger a manual sync.&lt;/li&gt;

  &lt;li&gt;Due to some Visual Studio implementation oddities, (a) the newly created code region is always expanded when it is inserted and (b) it happens that it doesn&amp;#39;t collapse automatically. There&amp;#39;s code in place that tries its best to collapse the region and most of the time it works, but when you&amp;#39;re tying furiously while sync kicks in - especially when you&amp;#39;re hitting Return as well to create new lines - the region might stay open. This doesn&amp;#39;t have any technical implications whatsoever, it just doesn&amp;#39;t look nice. I&amp;#39;m afraid there will probably not be a solution to this.&lt;/li&gt;

  &lt;li&gt;Finally, I&amp;#39;ve seen the need to reintroduce the snag of the dead redo list in Visual Studio, as previously reported in B91445 and CB54533. Okay okay, I&amp;#39;m joking, I didn&amp;#39;t do it on purpose. But I had to fiddle around with the undo handling after making those structural changes explained above, and for some reason everything now works differently... difference between using immediate and queued edits in DXCore, in case you&amp;#39;re curious. I have now managed to make undo work really nicely - it simply skips the automatic changes and undoes (is that a word?) whatever you actually did right before - but Visual Studio still kills the redo list... opening and then discarding an undo unit apparently does that, and I doubt there&amp;#39;s a way around it. My apologies to everybody who loves redo - personally I hardly ever use it, so I hope it&amp;#39;s not going to be the worst kind of showstopper. Oh yeah, and I should mention that this problem applies only to automatic sync! So using manual sync is once more a workaround if you really want redo functionality.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that&amp;#39;s it - please try the plugin and let me know if you find any problems. I apologize in advance for all issues I&amp;#39;ve introduced now - when making rather major changes like I did, breaking something also becomes more likely.&lt;/p&gt;
&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=230324" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO Publication Service update for 8.1.4</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/05/31/xpo-publication-service-update-for-8-1-4.aspx</link><pubDate>Sat, 31 May 2008 15:10:34 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:221896</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=221896</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/05/31/xpo-publication-service-update-for-8-1-4.aspx#comments</comments><description>&lt;p&gt;There are no changes in this version -- surprising as it may be, nobody ever reported a single bug in this tool. I expect that is because nobody is using it :-) Oh well.&lt;/p&gt; &lt;p&gt;If you don&amp;#39;t have a clue what this is about, see these previous posts for details:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://community.devexpress.com/blogs/xpo/archive/2006/10/13/announcing-the-xpo-publication-service.aspx"&gt;Announcing the XPO Publication Service&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://community.devexpress.com/blogs/xpo/archive/2006/10/16/xpo-publication-why.aspx"&gt;XPO Publication - Why?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://community.devexpress.com/blogs/xpo/archive/2006/10/16/publication-service-a-very-simple-example.aspx"&gt;Publication Service: a very simple example&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I updated the tool for XPO 8.1.4 and everything still seems to be working just like it did. Nice. Here are the downloads:&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.devexpress.com/blogs/xpo/XPOPublicationService-1.0.1.0.zip"&gt;XPOPublicationService-1.0.1.0.zip&lt;/a&gt; (36849 bytes)&lt;/p&gt; &lt;p&gt;&lt;a href="http://community.devexpress.com/blogs/xpo/XPOPublicationService-1.0.1.0-bin.zip"&gt;XPOPublicationService-1.0.1.0-bin.zip&lt;/a&gt; (40113 bytes)&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=221896" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>ANN: DXCore XPO plugin 1.1.0.7</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/04/11/ann-dxcore-xpo-plugin-1-1-0-7.aspx</link><pubDate>Fri, 11 Apr 2008 19:08:04 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:216951</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=216951</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/04/11/ann-dxcore-xpo-plugin-1-1-0-7.aspx#comments</comments><description>&lt;p&gt;Once again, a new version of the plugin, with a few bug fixes. If you&amp;#39;re not familiar with the purpose of the XPO plugin, please read &lt;a href="http://www.devexpress.com/Products/NET/Libraries/XPO/SimplifiedCriteriaSyntax.xml"&gt;this description of the &amp;quot;Simplified Criteria Syntax&amp;quot; feature&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;This is the download for version 1.1.0.7: &lt;a href="http://community.devexpress.com/blogs/xpo/CR_XPOFieldSync-1.1.0.7.zip"&gt;CR_XPOFieldSync-1.1.0.7.zip&lt;/a&gt; (21071 bytes)&lt;/p&gt; &lt;p&gt;Version 1.1.0.7 is compiled against DXCore 3.0.5. Here are the fixes I made:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Fixed B91445 and CB54533 - redo list being cleared by XPO plugins sync process.&lt;/li&gt; &lt;li&gt;Fixed Q99903 - no Field class entries for collection properties &lt;/li&gt; &lt;li&gt;Fixed part of B93229 - no Fields class entries for properties made persistent with ValueConverterAttribute&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The issue of CB8627 is still outstanding, as &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2007/03/22/839.aspx"&gt;described previously&lt;/a&gt;. I do have hope though that I&amp;#39;ll be able to solve that problem soon - I was actually working on it, but then it turned out that there&amp;#39;s a bug in DXCore that prevents it from happening at this time. I&amp;#39;ll get back to that issue as soon as possible.&lt;/p&gt; &lt;p&gt;As usual, if you have any other problems with the plugin, please &lt;a href="http://www.devexpress.com/support/center"&gt;let us know&lt;/a&gt;!&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=216951" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO, LINQ and Distinct</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/03/28/xpo-linq-and-distinct.aspx</link><pubDate>Fri, 28 Mar 2008 17:12:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:215352</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=215352</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/03/28/xpo-linq-and-distinct.aspx#comments</comments><description>XPO, LINQ and Distinct

&lt;p&gt;In &lt;a href="http://community.devexpress.com//forums/p/62591/212611.aspx#212611"&gt;a recent forum post&lt;/a&gt;, Dusan Pupis mentioned that our LINQ support didn&amp;#39;t currently include the Distinct extension method. I looked into this and I found a pretty complex situation that requires some explanation.&lt;/p&gt;

&lt;p&gt;First, in XPO 8.1.1, we do in fact support Distinct(), i.e. the overload that doesn&amp;#39;t take any further parameters, in some situations. For my test application, I&amp;#39;m using the following code based on three standard persistent classes:&lt;/p&gt;

&lt;pre&gt;XpoDefault.DataLayer = new SimpleDataLayer(&lt;br /&gt;  new DataStoreLogger(&lt;br /&gt;    new InMemoryDataStore(new DataSet( ), AutoCreateOption.SchemaOnly),&lt;br /&gt;    Console.Out));&lt;br /&gt;&lt;br /&gt;using (UnitOfWork uow = new UnitOfWork( )) {&lt;br /&gt;  Artist eltonJohn = new Artist(uow) { Name = &amp;quot;Elton John&amp;quot; };&lt;br /&gt;  eltonJohn.Albums.Add(new Album(uow) { Name = &amp;quot;Tumbleweed Connection&amp;quot;, Year = 1970 });&lt;br /&gt;  eltonJohn.Albums.Add(new Album(uow) { Name = &amp;quot;Don&amp;#39;t Shoot Me I&amp;#39;m Only the Piano Player&amp;quot;, Year = 1973 });&lt;br /&gt;  eltonJohn.Albums.Add(new Album(uow) { Name = &amp;quot;Too Low for Zero&amp;quot;, Year = 1983 });&lt;br /&gt;  eltonJohn.Albums.Add(new Album(uow) { Name = &amp;quot;Captain Fantastic and the Brown Dirt Cowboy&amp;quot;, Year = 1975 });&lt;br /&gt;  eltonJohn.Albums.Add(new Album(uow) { Name = &amp;quot;Caribou&amp;quot;, Year = 1974 });&lt;br /&gt;&lt;br /&gt;  Artist rollingStones = new Artist(uow) { Name = &amp;quot;The Rolling Stones&amp;quot; };&lt;br /&gt;  rollingStones.Albums.Add(new Album(uow) { Name = &amp;quot;Aftermath&amp;quot;, Year = 1966 });&lt;br /&gt;  rollingStones.Albums.Add(new Album(uow) { Name = &amp;quot;Their Satanic Majesties&amp;#39; Request&amp;quot;, Year = 1967 });&lt;br /&gt;  rollingStones.Albums.Add(new Album(uow) { Name = &amp;quot;Sticky Fingers&amp;quot;, Year = 1971 });&lt;br /&gt;  rollingStones.Albums.Add(new Album(uow) { Name = &amp;quot;It&amp;#39;s Only Rock &amp;#39;n&amp;#39; Roll&amp;quot;, Year = 1974 });&lt;br /&gt;  rollingStones.Albums.Add(new Album(uow) { Name = &amp;quot;Exile on Main Street&amp;quot;, Year = 1972 });&lt;br /&gt;  rollingStones.Albums.Add(new Album(uow) { Name = &amp;quot;Sucking in the Seventies&amp;quot;, Year = 1981 });&lt;br /&gt;&lt;br /&gt;  Artist procolHarum = new Artist(uow) { Name = &amp;quot;Procol Harum&amp;quot; };&lt;br /&gt;  procolHarum.Albums.Add(new Album(uow) { Name = &amp;quot;Procol Harum&amp;quot;, Year = 1967 });&lt;br /&gt;&lt;br /&gt;  Artist jethroTull = new Artist(uow) { Name = &amp;quot;Jethro Tull&amp;quot; };&lt;br /&gt;  jethroTull.Albums.Add(new Album(uow) { Name = &amp;quot;Thick as a Brick&amp;quot;, Year = 1972 });&lt;br /&gt;  jethroTull.Albums.Add(new Album(uow) { Name = &amp;quot;Minstrel in the Gallery&amp;quot;, Year = 1975 });&lt;br /&gt;&lt;br /&gt;  new TestData(uow) { Val1 = &amp;quot;One&amp;quot;, Val2 = &amp;quot;Two&amp;quot; }.Save( );&lt;br /&gt;  new TestData(uow) { Val1 = &amp;quot;Three&amp;quot;, Val2 = &amp;quot;Four&amp;quot; }.Save( );&lt;br /&gt;  new TestData(uow) { Val1 = &amp;quot;Four&amp;quot;, Val2 = &amp;quot;Two&amp;quot; }.Save( );&lt;br /&gt;  new TestData(uow) { Val1 = &amp;quot;One&amp;quot;, Val2 = &amp;quot;Two&amp;quot; }.Save( );&lt;br /&gt;&lt;br /&gt;  uow.CommitChanges( );&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;With this initialization, I can do a few things with Distinct. For example, I can find a distinct Album year like this:&lt;/p&gt;

&lt;pre&gt;using (UnitOfWork uow = new UnitOfWork( )) {&lt;br /&gt;  var albumYears =&lt;br /&gt;    from album in new XPQuery(uow)&lt;br /&gt;    select album.Year;&lt;br /&gt;&lt;br /&gt;  ObjectDumper.Write(albumYears.Distinct( ));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;Since I&amp;#39;m using the logger in my data layer, I can see that the query is this:&lt;/p&gt;

&lt;pre&gt;SelectData request with 1 queries:select(&amp;#39;N0&amp;#39;.&amp;#39;Year&amp;#39;) from(&amp;#39;Album&amp;#39;.&amp;#39;N0&amp;#39;) &lt;br /&gt;  where(IsNull(&amp;#39;N0&amp;#39;.&amp;#39;GCRecord&amp;#39;)) order() group(&amp;#39;N0&amp;#39;.&amp;#39;Year&amp;#39;) having() params() ;&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;Along the same lines, I can also query more than one value, this time using the TestData objects:&lt;/p&gt;

&lt;pre&gt;var testdata =&lt;br /&gt;  from test in new XPQuery(uow)&lt;br /&gt;  select new { Val1 = test.Val1, Val2 = test.Val2 };&lt;br /&gt;&lt;br /&gt;ObjectDumper.Write(testdata.Distinct());&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;This creates the following query:&lt;/p&gt;

&lt;pre&gt;SelectData request with 1 queries:select(&amp;#39;N0&amp;#39;.&amp;#39;Val1&amp;#39;,&amp;#39;N0&amp;#39;.&amp;#39;Val2&amp;#39;) from(&amp;#39;TestData&amp;#39;.&amp;#39;N0&amp;#39;) &lt;br /&gt;  where(IsNull(&amp;#39;N0&amp;#39;.&amp;#39;GCRecord&amp;#39;)) order() group(&amp;#39;N0&amp;#39;.&amp;#39;Val1&amp;#39;,&amp;#39;N0&amp;#39;.&amp;#39;Val2&amp;#39;) having() params() ;&lt;br /&gt;&lt;/pre&gt;


&lt;p&gt;As you can see, in both cases the XPQuery&amp;lt;T&amp;gt; has translated the query code into our query language, which in turn gets executed on the server. This is really the whole point of LINQ to XPO - bridging from LINQ syntax and extensions into the XPO world, where our database independent querying system can then execute the query efficiently on the server.&lt;/p&gt;

&lt;p&gt;Now here&amp;#39;s something that doesn&amp;#39;t work:&lt;/p&gt;

&lt;pre&gt;var result =&lt;br /&gt;  from artist in query&lt;br /&gt;  select artist;&lt;br /&gt;&lt;br /&gt;ObjectDumper.Write(result.Distinct());&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;Why not? Because the system can&amp;#39;t guess what it is that makes one Artist different from another. Of course there&amp;#39;s the primary key, but I don&amp;#39;t need Distinct for that one. All other distinctions are much more complex to describe, so Microsoft introduced another overload of the Distinct method:&lt;/p&gt;

&lt;pre&gt;public static IQueryable Distinct(&lt;br /&gt;  this IQueryable source, IEqualityComparer comparer);&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;This one takes a parameter for an IEqualityComparer implementation, and of course that interface allows me to specify precisely when a certain object is to be regarded equal to another object. However, this overload is not support by XPO, and will likely never be supported.&lt;/p&gt;

&lt;p&gt;There are two reasons for that. First, Microsoft decided to have this method take an interface as a parameter, not a lambda expression, like most of the other LINQ extension methods do. Of course we could create an overload ourselves that takes a lambda expression, but that brings us to reason number two: the code that determines equality is likely to be so complex that translating it into something that would run on the server would be impossible in the majority of cases. I don&amp;#39;t know if reason two is perhaps also the source of reason one, but it seems likely.&lt;/p&gt;

&lt;p&gt;There&amp;#39;s one easy way to use this overload of Distinct with XPO: simply make sure to use Enumerable.Distinct, pass in your IEqualityComparer and suddenly everything works. How does it work? Very simple: the data is retrieved from the server and Distinct runs over the client-side results, where the comparer code can be executed. We could have made this happen by default in the cases where translation isn&amp;#39;t possible, but we decided it would be safer not to do that. So it&amp;#39;s left to you to be explicit about this if your intention is to get Distinct executed client-side. Here&amp;#39;s how that works (for example - there are many different ways of making IEqualityComparer work for you):&lt;/p&gt;

&lt;pre&gt;// This is bad!!! Just an example. This results in Elton John&lt;br /&gt;// and Procol Harum being equals.&lt;br /&gt;class Comparer : EqualityComparer {&lt;br /&gt;  public override bool Equals(Artist x, Artist y) {&lt;br /&gt;    return GetHashCode(x) == GetHashCode(y);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override int GetHashCode(Artist obj) {&lt;br /&gt;    if (obj.Name == &amp;quot;Elton John&amp;quot; || obj.Name == &amp;quot;Procol Harum&amp;quot;)&lt;br /&gt;      return 734;&lt;br /&gt;    return obj.GetHashCode( );&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;  var result =&lt;br /&gt;    from artist in new XPQuery(uow)&lt;br /&gt;    select artist;&lt;br /&gt;&lt;br /&gt;  ObjectDumper.Write(((IEnumerable) result).Distinct(new Comparer( )));&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;The cast to IEnumerable&amp;lt;Artist&amp;gt; makes sure that the Distinct extension method is taken from the Enumerable class (because it&amp;#39;s declared as an extension on IEnumerable&amp;lt;T&amp;gt;). Of course there are other ways - you could call ToList() on the result before calling Distinct, or call Enumerable.Distinct without using the extension method syntax.&lt;/p&gt;


&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=215352" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/LINQ/default.aspx">LINQ</category></item><item><title>Four new Knowledge Base articles on eXpress Persistent Objects</title><link>http://community.devexpress.com/blogs/xpo/archive/2008/03/18/four-new-knowledge-base-articles-on-express-persistent-objects.aspx</link><pubDate>Tue, 18 Mar 2008 19:07:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:214098</guid><dc:creator>Nick (Developer Express)</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=214098</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2008/03/18/four-new-knowledge-base-articles-on-express-persistent-objects.aspx#comments</comments><description>&lt;p&gt;During the last few weeks I&amp;#39;ve had some time to kill so I decided to fill up our &lt;a href="http://www.devexpress.com/kb"&gt;Knowledge Base&lt;/a&gt; with new material on &lt;a href="http://www.devexpress.com/xpo"&gt;eXpress Persistent Object (XPO)&lt;/a&gt;. For me, this product can be thought of like an iceberg: At its surface, one sees only a small portion of what&amp;#39;s hiding underneath. With XPO, you need to know very little about the product to create your first application. But by digging a bit deeper you&amp;#39;ll uncover many new aspects of the product and hopefully appreciate its strengths and power, and feel even more confident to place it as the foundation of your data-aware applications.&lt;/p&gt;
&lt;p&gt;So, enough with the metaphors...here are a few articles to help you dig deeper into XPO in many unique ways: &lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.devexpress.com/kb=K18061"&gt;How to use XPO in an ASP.NET (Web) application&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.devexpress.com/kb=K18060"&gt;Getting started with XPO development for Compact devices&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.devexpress.com/kb=K18063"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.devexpress.com/kb=K18063"&gt;How to create a criterion, which returns an intersection of two many-to-many sets&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.devexpress.com/kb=K18072"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.devexpress.com/kb=K18072"&gt;How to implement self-referenced persistent objects, and to display these objects within the XtraTreeList&lt;/a&gt; &lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=214098" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>Some SetPropertyValue/GetPropertyValue overloads will be deprecated</title><link>http://community.devexpress.com/blogs/xpo/archive/2007/12/14/some-setpropertyvalue-getpropertyvalue-overloads-will-be-deprecated.aspx</link><pubDate>Fri, 14 Dec 2007 15:22:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:204551</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=204551</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2007/12/14/some-setpropertyvalue-getpropertyvalue-overloads-will-be-deprecated.aspx#comments</comments><description>&lt;p&gt;In future releases of XPO, we will deprecate certain overloads of the &lt;i&gt;SetPropertyValue&lt;/i&gt; and &lt;i&gt;GetPropertyValues&lt;/i&gt; in &lt;i&gt;XPBaseObject&lt;/i&gt;. In &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2007/02/01/701.aspx"&gt;a previous post of mine&lt;/a&gt; I have outlined some of the various combinations that can currently be used for property implementations in persistent classes, and the case that&amp;#39;s the subject of this post is &lt;b&gt;case 1&lt;/b&gt;.&lt;/p&gt; &lt;p&gt;There&amp;#39;s a nice little example and an explanation of this case in the original post, but here&amp;#39;s a quick summary. The overload in question is the one where the methods do not take a parameter for the property name. This was previously already a scenario that I marked &lt;b&gt;not recommended&lt;/b&gt;, because of performance as well as technical issues with it. The performance issues are simply due to the additional work that needs to be done on every single property access, the technical issues I&amp;#39;m referring to relate to changes in .NET 2. Again, for more details about the issues we&amp;#39;re having with this, please read &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2007/02/01/701.aspx"&gt;this blog post&lt;/a&gt; or feel free to &lt;a href="https://www.devexpress.com/support/center"&gt;contact our support team&lt;/a&gt; and request any information you need.&lt;/p&gt; &lt;p&gt;We have since had a number of support incidents, where programmers were not aware of the implications of this particular implementation, and were wondering about various side effects. In each of those cases, the problem could be solved simply by using one of the method overloads that take the property name as a parameter. As things are, we regret that we ever introduced this seemingly comfortable way of working with the helper methods. As there are now no perceivable advantages left of this approach, we have made the following decision:&lt;/p&gt; &lt;p&gt;&lt;b&gt;Over the next few releases, these method overloads are going to be marked obsolete, and then removed!&lt;br /&gt;&lt;font color="#ff0000"&gt;(Clarification: we are still talking about those overloads of SetPropertyValue and GetPropertyValue that &lt;i&gt;do not&lt;/i&gt; take a property name as one of their parameters!)&lt;/font&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt; &lt;p&gt;As a result, if you are using these overloads, you will start seeing warning messages from the &lt;i&gt;Obsolete&lt;/i&gt; attribute in one of the next XPO versions (I&amp;#39;m currently assuming 7.3.6, as 7.3.5 is just out the door). To solve this problem and make sure that your application does what it should (isn&amp;#39;t it nice that at least there&amp;#39;s some real purpose in this &amp;lt;g&amp;gt;), you will have to insert the property name into the parameter lists of all calls to &lt;i&gt;SetPropertyValue&lt;/i&gt; and &lt;i&gt;GetPropertyValue&lt;/i&gt; (it&amp;#39;s always the first parameter).&lt;/p&gt; &lt;p&gt;Please feel free to contact us in any way if you want to discuss the matter with us, register disagreement, or if you have questions.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=204551" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO - Using the class generation wizard</title><link>http://community.devexpress.com/blogs/xpo/archive/2007/07/24/xpo-using-the-class-generation-wizard.aspx</link><pubDate>Tue, 24 Jul 2007 15:11:37 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:189338</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=189338</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2007/07/24/xpo-using-the-class-generation-wizard.aspx#comments</comments><description>&lt;p&gt;Newest versions of XPO (since the 7.2 release) have a wizard that allows you to to create class structures from existing databases. This feature has been requested many times in the past, and we made first steps a while ago by including a tutorial project that supports MS SQL Server (if you&amp;#39;re curious, the tutorial is still included - it&amp;#39;s called &amp;quot;GeneratingPersistentClasses&amp;quot;). The new wizard takes things to the next level by supporting a variety of additional database systems, so we recommend you start using it instead of the tutorial application. If you give us feedback on the functionality, we will also consider extending it in the future.  &lt;p&gt;Using the feature is not difficult, but possibly not immediately obvious. In an existing project (currently with the exception of ASP.NET projects - see the end of this post), add a new item to the project and select &lt;em&gt;Persistent Classes X.X&lt;/em&gt; from the list of item types (the &lt;em&gt;X.X&lt;/em&gt; stands for the precise version of XPO you have installed). You can change the name of the new file to something more useful, but in practice I don&amp;#39;t find that very important because I&amp;#39;m going to change the file name anyway once the classes have been generated.  &lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;img src="http://community.devexpress.com/blogs/files/createpersistentclasses2.png" alt="" /&gt;  &lt;p&gt;&amp;nbsp; &lt;p&gt;Before anything is created, the template brings up a dialog that allows you to select the database provider you want to use, the database itself and any connection parameters, and finally the tables and columns you want to generate classes and properties for.  &lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;img src="http://community.devexpress.com/blogs/files/classcreation.png" alt="" /&gt;  &lt;p&gt;&amp;nbsp; &lt;p&gt;After this step, the class creation process is executed and the result is a new file in your project with all the new classes inside. The wizard currently leaves two important things to do:  &lt;ol&gt; &lt;li&gt;Renaming the classes. In traditional databases, tables regularly have weird names that I don&amp;#39;t want in my OO class structure. Even if the names aren&amp;#39;t weird, they may not be totally suitable. In the screenshot above you can see tables called &lt;em&gt;Categories&lt;/em&gt; and &lt;em&gt;Customers&lt;/em&gt; (plural). I would rename the resulting classes to &lt;em&gt;Category&lt;/em&gt; and &lt;em&gt;Customer&lt;/em&gt; (singular), because that makes more sense in an OO context.&lt;br /&gt;&lt;em&gt;Hint: if renaming sounds like a lot of work, have a look at &lt;/em&gt;&lt;a href="http://www.devexpress.com/refactor"&gt;&lt;em&gt;Refactor!&lt;/em&gt;&lt;/a&gt;&lt;em&gt; It has a &lt;/em&gt;&lt;a href="http://www.devexpress.com/Products/NET/IDETools/Refactor/whitepaper.xml#autolist2"&gt;Rename&lt;em&gt; refactoring&lt;/em&gt;&lt;/a&gt;&lt;em&gt; that makes this extremely easy.&lt;/em&gt;&lt;/li&gt; &lt;li&gt;Pull each of the new classes into its own file. Having a single class per file is a convention I recommend very much. Another thing Refactor! can help you with, btw. Why is it not done automatically? No idea, to be honest... but I think the current implementation isn&amp;#39;t so bad, because it leaves the decision to the developer and it makes search and replace type operations on the freshly generated source code much easier (for those who don&amp;#39;t use a tool like Refactor! &amp;lt;g&amp;gt;).&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;br /&gt;Finally, a word about ASP.NET projects. In the current release, the template &lt;em&gt;Persistent Classes X.X&lt;/em&gt; (as well as the standard template &lt;em&gt;Persistent Object X.X&lt;/em&gt;) is not available if the project type is ASP.NET. The reasons for this are somewhat complicated, you can find an explanation &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2007/07/24/xpo-and-asp-net-where-to-put-your-persistent-classes.aspx"&gt;here&lt;/a&gt;. We will fix this problem for the next minor update, meanwhile you can import persistent class declarations into a different project and move them over to the ASP.NET one - but do look out for &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2007/07/24/xpo-and-asp-net-where-to-put-your-persistent-classes.aspx"&gt;the guidelines given in this post&lt;/a&gt;.&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=189338" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO and ASP.NET - Where to put your persistent classes</title><link>http://community.devexpress.com/blogs/xpo/archive/2007/07/24/xpo-and-asp-net-where-to-put-your-persistent-classes.aspx</link><pubDate>Tue, 24 Jul 2007 15:00:54 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:189337</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=189337</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2007/07/24/xpo-and-asp-net-where-to-put-your-persistent-classes.aspx#comments</comments><description>&lt;p&gt;If you have been working with XPO in ASP.NET applications, you may have noticed that the standard XPO &lt;em&gt;Persistent Object X.X&lt;/em&gt; (and also the new &lt;em&gt;Persistent Classes X.X&lt;/em&gt;) template is not available when the current project is an ASP.NET project. We recently re-evaluated the decision to leave the templates out from that location, and while we found the original reason to be invalid by now, there are still some things to be aware of when working with persistent classes in ASP.NET projects.&lt;/p&gt; &lt;p&gt;Back in the days of beta testing for VS 2005, we first discovered a problem that appeared when persistent class hierarchies were used in ASP.NET projects. The reason for this issue was that XPO stores certain information about classes inside the database, among those the name of the assembly from which the class was originally read. A lot of the time this information is not used, but when persistent classes are derived from other persistent classes and instances of those derived classes are created and saved, XPO looks up the assembly name information and tries to demand-load the correct assembly. &lt;/p&gt; &lt;p&gt;In ASP.NET 2.0/VS 2005, a project is built (by default) into several assemblies, and the names of these assemblies include a &amp;quot;key&amp;quot; part that changes regularly after rebuilding. So when XPO stores away the assembly name of a certain class in a first application run, then that information is likely going to be invalid on a later run because by now the name of the assembly has changed.&lt;/p&gt; &lt;p&gt;When we discovered this issue originally, we found two workarounds. The first workaround is to enable a project level option in VS 2005, called &lt;em&gt;Use fixed naming and single page assemblies&lt;/em&gt; (you can find it on the &lt;em&gt;MSBuild Options&lt;/em&gt; page). While this makes sure that the assemblies have reliable static names,&amp;nbsp;it has the major disadvantage of creating lots of little assemblies, because every single (web) page now gets its own. Well.&lt;/p&gt; &lt;p&gt;The second workaround is still &lt;strong&gt;our current recommendation&lt;/strong&gt;, which is to use a &lt;strong&gt;separate assembly for&lt;/strong&gt; your &lt;strong&gt;persistent classes&lt;/strong&gt; -- a standard &amp;quot;class library&amp;quot; project type will do for this. Not only did this solve the issue above, it is also generally a good practice because it allows you to easily create other applications that use the same classes as your web application. Think of admin frontends running on Windows Forms, database update utilities and so on...&lt;/p&gt; &lt;p&gt;Now, in our recent re-evaluation we found something that was news to us: there is special magic implemented in the .NET framework, so that assemblies with a name that starts with &lt;em&gt;App_Code&lt;/em&gt; will be found even if the rest of their name doesn&amp;#39;t equal the search string. In other words, a call to &lt;em&gt;Assembly.Load(&amp;quot;App_Code.myRandomPostfix&amp;quot;)&lt;/em&gt; will load the actual &lt;em&gt;App_Code&lt;/em&gt; assembly when used from a web application, never mind the fact that the actual assembly obviously uses a different postfix. This magic handling seems to be in place for .NET 2.0 and above. We&amp;#39;re not quite sure why we didn&amp;#39;t see it earlier, but probably it was added before the final 2.0 release.&lt;/p&gt; &lt;p&gt;This discovery means that technically your persistent classes are safe when stored inside the &lt;em&gt;App_Code&lt;/em&gt; subfolder of your ASP.NET project. We will therefore make the templates available for use in those projects in the next minor update. I would still recommend you use a separate assembly, but at least we can get rid of a somewhat arbitrary restriction now.&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=189337" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>XPO and ASP.NET - a look at the initialization code</title><link>http://community.devexpress.com/blogs/xpo/archive/2007/07/20/xpo-and-asp-net-a-look-at-the-initialization-code.aspx</link><pubDate>Fri, 20 Jul 2007 14:26:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:189068</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=189068</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2007/07/20/xpo-and-asp-net-a-look-at-the-initialization-code.aspx#comments</comments><description>&lt;p&gt;Mehul got back to me yesterday and asked me to explain the &lt;a href="http://www.devexpress.com/xpo"&gt;XPO&lt;/a&gt; related initialization code that is being used in our new &lt;a href="http://demos.devexpress.com/ASPxGridViewDemos/"&gt;ASPxGridView&lt;/a&gt; demo. This is the code in question:&lt;/p&gt;&lt;pre class="code"&gt;    &lt;span&gt;void&lt;/span&gt; &lt;span&gt;Application_Start&lt;/span&gt;(&lt;span&gt;object&lt;/span&gt; &lt;span&gt;sender&lt;/span&gt;, &lt;span&gt;EventArgs&lt;/span&gt; &lt;span&gt;e&lt;/span&gt;) &lt;br /&gt;    {&lt;br /&gt;        &lt;span&gt;if&lt;/span&gt;(&lt;span&gt;DemoSettings&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;IsSiteMode&lt;/span&gt;) {&lt;br /&gt;            &lt;span&gt;ConnectionStringSettings&lt;/span&gt; &lt;span&gt;conn&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;br /&gt;                &lt;span&gt;ConfigurationManager&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ConnectionStrings&lt;/span&gt;[&lt;span&gt;&amp;quot;XPOServerMode&amp;quot;&lt;/span&gt;];&lt;br /&gt;            &lt;span&gt;if&lt;/span&gt;(&lt;span&gt;conn&lt;/span&gt; &lt;span&gt;!=&lt;/span&gt; &lt;span&gt;null&lt;/span&gt;) {&lt;br /&gt;                &lt;span&gt;// Code that runs on application startup&lt;br /&gt;&lt;/span&gt;                &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;XPDictionary&lt;/span&gt; &lt;span&gt;dict&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;br /&gt;                    &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ReflectionDictionary&lt;/span&gt;();&lt;br /&gt;                &lt;span&gt;dict&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetDataStoreSchema&lt;/span&gt;(&lt;span&gt;typeof&lt;/span&gt;(&lt;span&gt;ServerSideGridTest&lt;/span&gt;)&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Assembly&lt;/span&gt;);&lt;br /&gt;                &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;IDataStore&lt;/span&gt; &lt;span&gt;store&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;br /&gt;                    &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;XpoDefault&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetConnectionProvider&lt;/span&gt;(&lt;br /&gt;                    &lt;span&gt;conn&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ConnectionString&lt;/span&gt;, &lt;br /&gt;                    &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AutoCreateOption&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SchemaAlreadyExists&lt;/span&gt;);&lt;br /&gt;                &lt;span&gt;store&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DataCacheNode&lt;/span&gt;(&lt;br /&gt;                    &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DataCacheRoot&lt;/span&gt;(&lt;span&gt;store&lt;/span&gt;));&lt;br /&gt;                &lt;span&gt;object&lt;/span&gt; &lt;span&gt;layer&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ThreadSafeDataLayer&lt;/span&gt;(&lt;span&gt;dict&lt;/span&gt;, &lt;span&gt;store&lt;/span&gt;);&lt;br /&gt;                &lt;span&gt;Application&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;(&lt;span&gt;&amp;quot;XpoLayer&amp;quot;&lt;/span&gt;, &lt;span&gt;layer&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Great. Now what&amp;#39;s happening here? Let&amp;#39;s go over the method line by line:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span&gt;    if&lt;/span&gt;(&lt;span&gt;DemoSettings&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;IsSiteMode&lt;/span&gt;) { &lt;br /&gt;        &lt;span&gt;ConnectionStringSettings&lt;/span&gt; &lt;span&gt;conn&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;br /&gt;            &lt;span&gt;ConfigurationManager&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ConnectionStrings&lt;/span&gt;[&lt;span&gt;&amp;quot;XPOServerMode&amp;quot;&lt;/span&gt;]; &lt;/pre&gt;
&lt;p&gt;These are demo specific lines, nothing to do with XPO. In fact, when working with XPO it is a common practice to use helper methods on certain XPO classes to retrieve an auto-generated connection string instead of using a pre-created one. For SQL Server, for example, you&amp;#39;d want a call into &lt;code&gt;&lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;MSSqlConnectionProvider&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetConnectionString&lt;/span&gt;( &lt;span&gt;...&lt;/span&gt; );&lt;/code&gt; to get a connection string. There&amp;#39;s nothing wrong with the approach of storing away the connection string, but it&amp;#39;s certainly a little easier to break.&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;&lt;span&gt;    DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;XPDictionary&lt;/span&gt; &lt;span&gt;dict&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;br /&gt;        &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Metadata&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ReflectionDictionary&lt;/span&gt;(); &lt;/pre&gt;
&lt;p&gt;The dictionary of metadata that XPO works with contains important information about the persistent classes in your application, and it is associated with the so-called data layer (an object that implements &lt;i&gt;IDataLayer&lt;/i&gt;, if you want to be technical about it). In general, a data layer is only created once per application, so the metadata dictionary is also created just once. &lt;/p&gt;
&lt;p&gt;In a Windows Forms application the code related to configuring the data layer is typically much simpler, probably something like this:&lt;/p&gt;&lt;pre class="code"&gt;    &lt;span&gt;XpoDefault&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DataLayer&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;XpoDefault&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetDataLayer&lt;/span&gt;( &lt;span&gt;...&lt;/span&gt; );&lt;/pre&gt;
&lt;p&gt;In ASP.NET, things are not quite as simple because we have to deal with the fact that we&amp;#39;re working in a multi-threaded environment. If you take a little peak ahead in the complete code of the &lt;i&gt;Application_Start&lt;/i&gt; method above, you will see a class called &lt;i&gt;ThreadSafeDataLayer&lt;/i&gt; being instantiated. This specific implementation of &lt;i&gt;IDataLayer&lt;/i&gt; can work in multi-threaded applications, but it requires a metadata dictionary that is stable during the application&amp;#39;s lifetime. A data layer in a Windows Forms (single threaded) application would be extended during the application run, depending on the classes that are being used. This is not allowed to happen in the ASP.NET multi-threaded scenario, and that&amp;#39;s why we have to create and fill the metadata dictionary manually, and before creating the data layer.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;    dict&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetDataStoreSchema&lt;/span&gt;(&lt;span&gt;typeof&lt;/span&gt;(&lt;span&gt;ServerSideGridTest&lt;/span&gt;)&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Assembly&lt;/span&gt;); &lt;/pre&gt;
&lt;p&gt;This line does the work: it needs an assembly reference (or several actually, it is possible to pass in more than one assembly reference at once), finds all the metadata in that assembly and adds it to the dictionary. To get to the correct assembly reference, one of the persistent types in the application is used to find the reference dynamically. This is an arbitrary persistent type in your application -- it looks a bit a hack, but it&amp;#39;s one of the easiest ways of getting hold of such a reference.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;    DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;IDataStore&lt;/span&gt; &lt;span&gt;store&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;br /&gt;        &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;XpoDefault&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetConnectionProvider&lt;/span&gt;( &lt;br /&gt;        &lt;span&gt;conn&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ConnectionString&lt;/span&gt;, &lt;br /&gt;        &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AutoCreateOption&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SchemaAlreadyExists&lt;/span&gt;); &lt;/pre&gt;
&lt;p&gt;Now we are ready to create a connection provider object, which is an object that implements the interface &lt;i&gt;IDataStore&lt;/i&gt;. This is basically the DB specific driver that XPO needs to communicate with your backend of choice. The &lt;i&gt;&lt;span&gt;XpoDefault&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;GetConnectionProvider( ... )&lt;/span&gt;&lt;/i&gt;&amp;nbsp;method analyzes the connection string to find out which type of connection provider it needs to create. For connection strings that are retrieved from the XPO helper methods (see above), there&amp;#39;s a special flag inserted into the connection string that simplifies identification. In the ASPxGridView demo, the connection string is read from the &lt;i&gt;Web.config&lt;/i&gt; file, but it still contains the flag. Here&amp;#39;s the string (wrapped):&lt;/p&gt;&lt;pre class="code"&gt;&lt;span&gt;    XpoProvider=MSSqlServer;data source=(local);user id=servermodeprojects;&lt;br /&gt;        &lt;/span&gt;&lt;span&gt;password=smp$;initial catalog=ServerModeGridProjects;Persist Security Info=true&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;The first parameter &lt;i&gt;XpoProvider&lt;/i&gt; tells the &lt;i&gt;GetConnectionString&lt;/i&gt; method that it needs to instantiate the connection provider for MS SQL Server in this case. If your connection string doesn&amp;#39;t have such a flag, there are heuristics in that method trying to recognize the string nevertheless, but this may not work totally reliably. You should either retrieve the connection string from one of the helper methods or make sure the flag is in there if you store the complete connection string in a config file.&lt;/p&gt;
&lt;p&gt;Finally, there&amp;#39;s an enum &lt;span&gt;&lt;i&gt;AutoCreateOption&lt;/i&gt;&lt;/span&gt; being passed into that method. This tells XPO how to handle the database schema - &lt;i&gt;SchemaAlreadyExists&lt;/i&gt; says that the schema shouldn&amp;#39;t be created, because it is expected to be there already. There are several &lt;a href="http://www.devexpress.com/Help/Content.aspx?help=XtraData&amp;amp;document=DevExpressXpoDBAutoCreateOptionEnumtopic.htm"&gt;other alternatives documented in the XPO product documentation&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;    store&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DataCacheNode&lt;/span&gt;( &lt;br /&gt;        &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DB&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;DataCacheRoot&lt;/span&gt;(&lt;span&gt;store&lt;/span&gt;)); &lt;/pre&gt;
&lt;p&gt;This line wraps the &lt;i&gt;IDataStore&lt;/i&gt; in instances of &lt;i&gt;DataCacheRoot &lt;/i&gt;and &lt;i&gt;DataCacheNode&lt;/i&gt;. &lt;i&gt;DataCacheNode &lt;/i&gt;implements &lt;i&gt;IDataStore &lt;/i&gt;itself, so the result of the operation can be used anywhere a &amp;quot;normal&amp;quot; connection provider can also be used. The purpose of the wrapping is to establish data layer caching, as described in &lt;a href="http://www.devexpress.com/Products/NET/Libraries/XPO/SessionManagementCaching.xml"&gt;this technical article&lt;/a&gt;.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;    object&lt;/span&gt; &lt;span&gt;layer&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;DevExpress&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Xpo&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ThreadSafeDataLayer&lt;/span&gt;(&lt;span&gt;dict&lt;/span&gt;, &lt;span&gt;store&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;With the metadata dictionary and the connection provider in hand, we can finally create our thread-safe data layer. I don&amp;#39;t know why the person who wrote the demo used &lt;span&gt;object&lt;/span&gt; as the type -- it should really be something explicit, must likely &lt;i&gt;IDataLayer&lt;/i&gt;.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;    Application&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;(&lt;span&gt;&amp;quot;XpoLayer&amp;quot;&lt;/span&gt;, &lt;span&gt;layer&lt;/span&gt;); &lt;/pre&gt;
&lt;p&gt;This line of code stores the data layer away for later use. Apart from the ASP.NET specific approach used here, there&amp;#39;s also a mechanim built into XPO to set a default data layer: the static &lt;i&gt;XpoDefault.DataLayer&lt;/i&gt; property. The main difference is that if &lt;i&gt;XpoDefault.DataLayer&lt;/i&gt; has been set, it is no longer necessary to pass in an explicit data layer reference when constructing instances of &lt;i&gt;Session&lt;/i&gt; or &lt;i&gt;UnitOfWork&lt;/i&gt;. Of course there&amp;#39;s the general argument that this works only as long as just one data layer is being used in an application, but that is really very common -- as I hear, the approach was chosen in this case becauses use of the &lt;i&gt;Application&lt;/i&gt; class for this kind of thing is regarded as a good practice in ASP.NET applications. Wouldn&amp;#39;t necessarily convince me, but there you go.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=189068" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/ASPxGridView/default.aspx">ASPxGridView</category><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>Receiving SqlDependency notifications for use outside XPO</title><link>http://community.devexpress.com/blogs/xpo/archive/2007/05/25/receiving-sqldependency-notifications-for-use-outside-xpo.aspx</link><pubDate>Fri, 25 May 2007 12:56:00 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:184625</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=184625</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2007/05/25/receiving-sqldependency-notifications-for-use-outside-xpo.aspx#comments</comments><description>
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
 
&lt;p&gt;Well, there&amp;#39;s obviously one really easy way to do it: just hook into the SqlDependency feature independently from XPO and receive the notifications that way. But there&amp;#39;s an easier way to do it if XPO is hooking these notifications anyway. I got some code from an XPO&amp;nbsp;developer and I created a sample around it to show how it works.&lt;/p&gt;
 
&lt;p&gt;&lt;b&gt;Note: &lt;/b&gt;Before that developer agreed to give me his code, he made me promise to say this: we really don&amp;#39;t recommend you use this! It is an approach that will have severe performance drawbacks in many multi-user scenarios. If you end up actually using it, please make sure you do testing on your application in circumstances that resemble production use. If you find that you have performance problems - which we believe is very likely -, we will not be able to do anything about it on the XPO level. Please consider yourself warned.&lt;/p&gt;
 
&lt;p&gt;Now you&amp;#39;re probably asking: &amp;quot;why is he going to post a sample if he doesn&amp;#39;t want me to use it?&amp;quot; Well, I believe that it is better to explain things to people, including (potentially) bad things, and let them make up their own minds. So here we go.&lt;/p&gt;
 
&lt;p&gt;The sample I&amp;#39;m using is the same I showed in &lt;a href="http://community.devexpress.com/blogs/xpo/archive/2007/05/16/xpo-beta-feature-sqldependency-support.aspx"&gt;the previous post about the SqlDependency feature&lt;/a&gt;. You can download the whole source code below. For the purpose of notification, the sample now includes a new class called &lt;b&gt;DataStoreChangeTrackingWrapper&lt;/b&gt;, which has two important (and a bunch of not as important) methods:&lt;/p&gt;
&lt;pre class="c#"&gt;	...
	protected void ProcessChanges(DataCacheResult result) {
		CurrentCookie = result.Cookie;
		if (result.UpdatedTableAges == null)
			OnEverythingChanged( );
		else if (result.UpdatedTableAges.Count &amp;gt; 0)
			OnTablesChanged(result.UpdatedTableAges.Keys);
	}
	...
	public void CatchUp( ) {
		DataCacheResult result = Root.NotifyDirtyTables(CurrentCookie);
		ProcessChanges(result);
	}
	...&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;DataStoreChangeTrackingWrapper&lt;/b&gt; class is a data store implementation. It overrides the &lt;b&gt;ProcessUpdateSchema&lt;/b&gt;, &lt;b&gt;ProcessSelectData&lt;/b&gt; and &lt;b&gt;ProcessModifyData&lt;/b&gt; methods and makes sure that &lt;b&gt;ProcessChange&lt;/b&gt; is called during the execution of all these methods. So if the application accesses the data store regularly (like the sample application does in its loop), the &lt;b&gt;OnEverythingChanged&lt;/b&gt; and &lt;b&gt;OnTablesChanged&lt;/b&gt; methods are going to be called automatically. The &lt;b&gt;CatchUp&lt;/b&gt; method is for those cases where the regularity is not there - a timer could be used to call into CatchUp regularly to make sure that updates are passed through.&lt;/p&gt;

&lt;p&gt;The two methods &lt;b&gt;OnEverythingChanged&lt;/b&gt; and&amp;nbsp;&lt;b&gt;OnTablesChanged&lt;/b&gt; are those that get called once changes have been detected&amp;nbsp;in the database. OnTablesChanged is the more common of the two, and it gets&amp;nbsp;more detailed information as well. OnEverythingChanged&amp;nbsp;is called only in cases where the cache&amp;nbsp;gets disconnected - for instance when the cache root service&amp;nbsp;is stopped in the case of a remotely published cache root.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;If you run the sample application and follow the same steps as in the previous article, you should see that at the point where external changes are being discovered, information about them will appear in the console. The sample uses a 5 second sleep in the main loop (previously one second), so that it&amp;#39;s easy to spot the additional output line.&lt;/p&gt;

&lt;p&gt;Download the sample here: &lt;a href="http://community.devexpress.com/blogs/files/XPOSqlServer2005CacheAndNotification2.zip"&gt;XPOSqlServer2005CacheAndNotification2.zip (4640 bytes)&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://community.devexpress.com/aggbug.aspx?PostID=184625" width="1" height="1"&gt;</description><category domain="http://community.devexpress.com/blogs/xpo/archive/tags/XPO/default.aspx">XPO</category></item><item><title>XPO Beta feature: SqlDependency support</title><link>http://community.devexpress.com/blogs/xpo/archive/2007/05/16/xpo-beta-feature-sqldependency-support.aspx</link><pubDate>Wed, 16 May 2007 15:57:28 GMT</pubDate><guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:183962</guid><dc:creator>Oliver Sturm (Developer Express)</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://community.devexpress.com/blogs/xpo/rsscomments.aspx?PostID=183962</wfw:commentRss><comments>http://community.devexpress.com/blogs/xpo/archive/2007/05/16/xpo-beta-feature-sqldependency-support.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx"&gt;SqlDependency&lt;/a&gt; is a &lt;strong&gt;SQL Server 2005 feature&lt;/strong&gt; that allows the database server to notify a client when changes occur in the database. &lt;a href="http://www.devexpress.com/Products/NET/Libraries/XPO/SessionManagementCaching.xml"&gt;XPO already has a strong caching infrastructure&lt;/a&gt;, but up until now it didn&amp;#39;t have support for the SqlDependency feature. We will introduce this support in our DXperience 7.2 release, and the recent 7.1.3 release includes the feature &lt;strong&gt;as a beta&lt;/strong&gt;. Please go ahead and test it and let us know of any problems you may find, but don&amp;#39;t rely on its stability until 7.2 is released.&lt;/p&gt; &lt;h4&gt;Prerequisites&lt;/h4&gt; &lt;p&gt;To make the SqlDependency feature work, there are some requirements that have to be kept. &lt;a href="http://msdn2.microsoft.com/en-us/library/aewzkxxh(VS.80).aspx"&gt;Microsoft has all the information about this on MSDN&lt;/a&gt;.&lt;/p&gt; &lt;h4&gt;A test program&lt;/h4&gt; &lt;p&gt;To demonstrate how the feature in XPO works, I have created a small test program. It starts out like this (I left out the Person class - it&amp;#39;s a standard persistent class, please download the source from below&amp;nbsp;if you need it):&lt;/p&gt;&lt;pre class="c#"&gt;static void Main(string[] args) {
	XpoDefault.DataLayer =
		new SimpleDataLayer(new DataCacheNode(new DataCacheRoot(
		XpoDefault.GetConnectionProvider(
		MSSqlConnectionProvider.GetConnectionString(
		&amp;quot;(local)&amp;quot;, &amp;quot;XPOSqlServer2005CacheAndNotification&amp;quot;),
		AutoCreateOption.DatabaseAndSchema))));

	using (Session initSession = new Session( )) {
		initSession.UpdateSchema(typeof(Person), typeof(XPObjectType));
	}

	for (; ; ) {
		using (UnitOfWork uow = new UnitOfWork( )) {
			Console.Clear( );
			XPCollection people = new XPCollection(uow);
			if (people.Count &amp;gt; 0)
				foreach (Person p in people)
					Console.WriteLine(&amp;quot;Key: {0} Person: {1}&amp;quot;, p.Oid, p.Name);
			else
				Console.WriteLine(&amp;quot;Empty collection&amp;quot;);
			Thread.Sleep(1000);
		}
	}
}
&lt;/pre&gt;
&lt;p&gt;As you can see, the program simply sets up a cached connection provider, creates all the table structures for the Person class, and then goes into a loop, querying again and again for all the Person instances in the database. Now, of course I am interested to see what queries actually go through to the database, so I also activate logging in the App.config (&lt;a href="https://www.devexpress.com/Support/Center/ViewKBIssue.aspx?kbid=A2572"&gt;see here for the background on that&lt;/a&gt;):&lt;/p&gt;&lt;pre class="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;
&amp;lt;configuration&amp;gt;
	&amp;lt;system.diagnostics&amp;gt;
		&amp;lt;switches&amp;gt;
			&amp;lt;add name=&amp;quot;XPO&amp;quot; value=&amp;quot;3&amp;quot; /&amp;gt;
		&amp;lt;/switches&amp;gt;
	&amp;lt;/system.diagnostics&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now I run the application, and of course there&amp;#39;s nothing in the database. The console shows &amp;quot;Empty collection&amp;quot; and the log output is also restricted to the minimum - note how the queries against the database are run just once, as the caching layer catches all the rest.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://community.devexpress.com/blogs/files/XPOBetafeatureSqlDependencysupport_EDED/consoleemptycollection4.png"&gt;&lt;img height="150" src="http://community.devexpress.com/blogs/files/XPOBetafeatureSqlDependencysupport_EDED/consoleemptycollection_thumb2.png" width="297" alt="" /&gt;&lt;/a&gt;&amp;nbsp;&lt;a href="http://community.devexpress.com/blogs/files/XPOBetafeatureSqlDependencysupport_EDED/immediatewindowoneselect4.png"&gt;&lt;img height="150" src="http://community.devexpress.com/blogs/files/XPOBetafeatureSqlDependencysupport_EDED/immediatewindowoneselect_thumb2.png" width="305" alt="" /&gt;&lt;/a&gt; &lt;/p