<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.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>Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx</link><description>(sorry, tricky problem -&amp;gt; long write-up) One of the few things pending in the server library of the ADO.NET Data Services Framework is query caching to help with performance. Here is a brief explanation of why we needed and a couple of design options.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Airline Travel &amp;raquo; Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8346831</link><pubDate>Tue, 01 Apr 2008 02:09:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8346831</guid><dc:creator>Airline Travel » Looking for feedback: query caching in data services</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://www.travel-hilarity.com/airline_travel/?p=2357"&gt;http://www.travel-hilarity.com/airline_travel/?p=2357&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>Query caching in ADO.NET Data Services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8346860</link><pubDate>Tue, 01 Apr 2008 02:30:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8346860</guid><dc:creator>Marcelo's WebLog</dc:creator><description>&lt;p&gt;Pablo has a new post on the Project Astoria Team blog about a few ideas we're considering on how to cache&lt;/p&gt;
</description></item><item><title>re: Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8347320</link><pubDate>Tue, 01 Apr 2008 07:35:21 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8347320</guid><dc:creator>Eric J. Smith</dc:creator><description>&lt;p&gt;What happens if you want to restrict the data by what the user specifically has access to and not by roles? &amp;nbsp;Would that still be possible?&lt;/p&gt;
</description></item><item><title>re: Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8347332</link><pubDate>Tue, 01 Apr 2008 07:40:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8347332</guid><dc:creator>pabloc</dc:creator><description>&lt;p&gt;Eric: yes, that would be possible in both of the approaches discussed here; in fact, that's why we're looking at this in so much depth; we want to make sure this is a good low-level mechanism to implement various row-level access policies on top. For the particular case of per-user access, you could have a table in the database that holds the access-control entries indicating which users get to see which records. At the interceptor level you'd write a predicate that injects lookups into those tables as conditions (which is what the &amp;quot;CustomerAccess&amp;quot; property hints at in the samples of the blog post).&lt;/p&gt;
&lt;p&gt;-pablo&lt;/p&gt;
</description></item><item><title>re: Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8362429</link><pubDate>Sun, 06 Apr 2008 09:58:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8362429</guid><dc:creator>Aleksandar</dc:creator><description>&lt;p&gt;I would favor performance in expense of usability of interceptor code and here is why. We are using ADO.NET Data Services for our core banking application and our mechanics for restricting access to entity instances is based on combination of entity ownership, OU hierarchy, team membership and entity sharing. In runtime expressions are supplied with user attributes extracted from security context and the pattern is the same for all entities. I expect that anyone writing security interceptors will avoid case by case expressions for different entities and seek to apply uniform pattern. Since devising this pattern is one time job, usability shouldn't be a problem.&lt;/p&gt;
&lt;p&gt;Aleksandar &lt;/p&gt;
</description></item><item><title>re: Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8362523</link><pubDate>Sun, 06 Apr 2008 11:03:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8362523</guid><dc:creator>pabloc</dc:creator><description>&lt;p&gt;Aleksandar: thanks for the feedback. Do you have examples of interceptors you can share (in this blog or offline)? I'd be curious to see what are the patterns for the interceptors you're using, both from the query perspective and from the point of view of dependencies from the environment. &lt;/p&gt;
&lt;p&gt;Do you use information from the runtime context (e.g. request header, login, etc.) to establish the criteria for filtering?&lt;/p&gt;
&lt;p&gt;Thanks,&lt;/p&gt;
&lt;p&gt;-pablo&lt;/p&gt;
</description></item><item><title>re: Looking for feedback: query caching in data services</title><link>http://blogs.msdn.com/astoriateam/archive/2008/03/31/looking-for-feedback-query-caching-in-data-services.aspx#8418285</link><pubDate>Wed, 23 Apr 2008 09:04:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8418285</guid><dc:creator>Michael Brundage</dc:creator><description>&lt;p&gt;Hi Pablo,&lt;/p&gt;
&lt;p&gt;Well, now OnStartRequest and InitializeService need to stay in sync somehow. &amp;nbsp;Either you statically verify this, or developers are going to experience considerable debugging pain.&lt;/p&gt;
&lt;p&gt;Perhaps this could be automated...&lt;/p&gt;
&lt;p&gt;What's really going on here is that you've allowed implicit variables (environment methods like GetUser() and the properties on the objects those methods return). &amp;nbsp;I could write a query interceptor that looks at your user agent or any other http headers that were passed with the request (?).&lt;/p&gt;
&lt;p&gt;Astoria controls the environment APIs that the query interceptors access -- methods like GetUser(). &amp;nbsp;You could return a proxy object from every such method, and on those proxies intercept the property accessors (UserDescriptor.IsAdmin, UserDescriptor.UserID, etc.). &amp;nbsp;When the query runs the first time, Astoria could record every implicit parameter upon which the query depended, and include those values as part of the cache key. &amp;nbsp;When a subsequent query passes the same parameters, you can return the result (result cache). &amp;nbsp;When it passes different parameters, you may be able to re-evaluate only the interceptors, or you might need to re-compile the whole query.&lt;/p&gt;
&lt;p&gt;In your example above, suppose IsAdmin is true the first time the query is executed. &amp;nbsp;Astoria memoizes the query tree with all its dependent parameters includeing IsAdmin. &amp;nbsp;Subsequently another query comes in with IsAdmin false. &amp;nbsp;Astoria re-evaluates the interceptor, which now reads UserID which was not previously read, invalidating the query cache.&lt;/p&gt;
&lt;p&gt;You could add an extra layer or two of cleverness to this. &amp;nbsp;Clever #1: diff the two query plans and cache the part they had in common. &amp;nbsp;Clever #2: push the if test into the predicate. &amp;nbsp;See, when IsAdmin was true, there's no where clause in the query plan, and when IsAdmin is false, there is. &amp;nbsp;So you can push the IsAdmin test into the where clause also -- this query interceptor can be entirely pushed into the database.&lt;/p&gt;
&lt;p&gt;Two other approaches that are more wildly divergent from your current model:&lt;/p&gt;
&lt;p&gt;1. 80% rule. &amp;nbsp;Recognize that paging and user auth are the things that tend to vary most, and special-case those.&lt;/p&gt;
&lt;p&gt;2. Treat queries as resources -- stored queries, if you will. &amp;nbsp;The user stores the query resource (with all parameters made explicit, including those that interceptors depend on) and can then GET the query results by hitting the endpoint and passing parameters. &amp;nbsp;The query cache becomes just an ordinary endpoint cache. &amp;nbsp;Personally I like this model best, because it's simple and implements the system using the system.&lt;/p&gt;
</description></item></channel></rss>