I wanted to be able to cache the results of a query from the LinqDataSource that was used in multiple places on the page. I whipped up this little class to do the work of caching for me. The class, LinqCacheDataSource, handles the Selecting and Selected events. The Selected handler inserts the result of the query into cache. The Selecting handler gets the result from the cache. If it doesn't find the result, the query runs as normal. The caching will only work for selecting data. It works great for dropdowns and other fairly static data.
The Code ...
/// <summary>
/// A LinqDataSource that provides caching for Linq queries.
/// </summary>
public class LinqCacheDataSource : LinqDataSource
{
/// <summary>
/// Initializes a new instance of the <see cref="LinqCacheDataSource"/> class.
/// </summary>
public LinqCacheDataSource()
: base()
{
this.Selecting += new EventHandler<LinqDataSourceSelectEventArgs>(OnSelecting);
this.Selected += new EventHandler<LinqDataSourceStatusEventArgs>(OnSelected);
}
private void OnSelecting(object sender, LinqDataSourceSelectEventArgs e)
{
if (!EnableCache)
return;
string key = GetKey();
object source = Context.Cache[key];
if (source == null)
return;
Debug.WriteLine("Cache Hit: " + key);
e.Result = source;
}
private void OnSelected(object sender, LinqDataSourceStatusEventArgs e)
{
if (!EnableCache)
return;
if (e.Exception != null || e.Result == null)
return;
string key = GetKey();
object source = Context.Cache[key];
if (source != null)
return;
Debug.WriteLine("Cache Insert: " + key);
Context.Cache.Insert(key, e.Result, null,
DateTime.Now.AddSeconds(Duration), Cache.NoSlidingExpiration);
}
private string GetKey()
{
StringBuilder sb = new StringBuilder();
sb.Append(this.ContextTypeName);
sb.Append(" from ");
sb.Append(this.TableName);
if (!string.IsNullOrEmpty(this.Select))
{
sb.Append(" select ");
sb.Append(this.Select);
}
if (!string.IsNullOrEmpty(this.Where))
{
sb.Append(" where ");
sb.Append(this.Where);
}
if (!string.IsNullOrEmpty(this.OrderBy))
{
sb.Append(" OrderBy ");
sb.Append(this.OrderBy);
}
return sb.ToString();
}
/// <summary>
/// Gets or sets a value indicating whether query caching is enabled.
/// </summary>
[DefaultValue(true)]
[Category("Cache")]
[Description("Enable caching the linq query result.")]
public bool EnableCache
{
get
{
object result = this.ViewState["EnableCache"];
if (result != null)
return (bool)result;
return true;
}
set
{
this.ViewState["EnableCache"] = value;
}
}
/// <summary>
/// Gets or sets the time, in seconds, that the query is cached.
/// </summary>
[DefaultValue(30)]
[Category("Cache")]
[Description("The time, in seconds, that the query is cached.")]
public int Duration
{
get
{
object result = this.ViewState["Duration"];
if (result != null)
return (int)result;
return 30;
}
set
{
this.ViewState["Duration"] = value;
}
}
}
PLINQO, which stands for Professional LINQ to Objects, is a collection
of CodeSmith templates that are meant to replace and extend the LINQ to
SQL designers that are included with Visual Studio 2008.
Features
- Generate or update a LINQ to SQL dbml file from a database schema.
- Includes all tables, stored procedures, functions, and views with the ability to exclude objects based on regex patterns.
- Ability to automatically remove object prefix and suffixes (ie. tbl_ and usp_).
- Dbml file can still be customized with the normal Visual Studio 2008 designer.
- Dbml file can be refreshed based on the current database schema without losing customizations. (See Safe Attributes)
- Generation of the LINQ to SQL DataContext class.
- Generation of the LINQ to SQL entity classes.
- Generates one file per entity instead of one massive file.
- Generates partial classes where custom code can be written and won't be overwritten.
- Generated entity files are added to the project as code behind files to their corresponding custom entity files.
- Generation of entity manager classes.
- Adds customizable business rules engine to enforce entity validation, business and security rules.
- Provides access to common queries based on primary keys, foreign keys, and indexes.
- Common queries are exposed as IQueryable so they can be extended.
- All templates can be customized to meet your needs.
Read More
http://community.codesmithtools.com/blogs/pwelter/archive/2007/08/08/plinqo.aspx
Download
http://www.codeplex.com/codesmith/Release/ProjectReleases.aspx
The following query extension will make paging a query more natural then skip and take. Simply append Paginate(page, pageSize) to your query.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace System.Linq
{
public static class PageQuery
{
public static IQueryable<T> Paginate<T>(
this IQueryable<T> query, int page, int pageSize)
{
int skip = Math.Max(pageSize * (page - 1), 0);
return query.Skip(skip).Take(pageSize);
}
}
}
I'd like to announce the release of a little project I've been working on. I call it Calculator.NET. I started this project for a couple reasons. First, I was annoyed that Windows Vista doesn't come with a better calculator. Windows XP has Power Calculator, but that doesn't work on Vista. Next, I was reading a blog about DynCalc by Bart De Smet on how to do mathematical calculations. That gave me the starting point on how to create Calculator.NET.
As part of the project, I created a MathExpressions library that does the bulk of work. The library supports math expressions, functions unit conversion and variables. Below are some examples of using the library directly.
MathEvaluator eval = new MathEvaluator();
//basic math
double result = eval.Evaluate("(2 + 1) * (1 + 2)");
//calling a function
result = eval.Evaluate("sqrt(4)");
//evaluate trigonometric
result = eval.Evaluate("cos(pi * 45 / 180.0)");
//convert inches to feet
result = eval.Evaluate("12 [in->ft]");
//use variable
result = eval.Evaluate("answer * 10");
//add variable
eval.Variables.Add("x", 10);
result = eval.Evaluate("x * 10");
Calculator that evaluates math expressions.

Calculator.NET Features
- Evaluate math expressions including grouping
- Support trigonometry and other function
- Common unit conversion of the following types
- Length
- Mass
- Speed
- Temperature
- Time
- Volume
- Variable support including last answer
Download Calculator.NET
XML Serializable Generic Dictionary
For some reason, the generic Dictionary in .net 2.0 is not XML serializable. The following code snippet is a xml serializable generic dictionary. The dictionary is serialzable by implementing the IXmlSerializable interface.
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
#endregion
}
Update: Fixed bug Justin pointed out by adding an extra reader.ReadEndElement() and by checking the IsEmptyElement property.
Announcement
The MSBuild Community Tasks Project releases version v1.1.0.145. There are many new tasks in this release. Special thanks to all the contributors to the project.
Current Community Tasks
| Task | Description |
| AppPoolController | Allows control for an application pool on a local or remote machine with IIS installed. |
| AppPoolCreate | Creates a new application pool on a local or remote machine. |
| AppPoolDelete | Deletes an existing application pool on a local or remote machine. |
| AssemblyInfo | Generates an AssemblyInfo file using the attributes given. |
| Attrib | Changes the attributes of files and/or directories |
| FileUpdate | Replace text in file(s) using a Regular Expression. |
| FtpUpload | Uploads a file using File Transfer Protocol (FTP). |
| FxCop | Uses FxCop to analyze managed code assemblies and reports on their design best-practice compliance. |
| Mail | Sends an email message. |
| Math.Add | Add numbers. |
| Math.Divide | Divide numbers. |
| Math.Multiple | Multiple numbers. |
| Math.Subtract | Subtract numbers. |
| Move | Moves files on the filesystem to a new location. |
| NDoc | Runs NDoc to create documentation. |
| NUnit | Runs tests using the NUnit. |
| RegistryRead | Reads a value from the Registry. |
| RegistryWrite | Writes a value to the Registry. |
| Script | Executes code contained within the task. |
| ServiceController | Task that can control a Windows service. |
| ServiceQuery | Task that can determine the status of a service. |
| Sleep | A task for sleeping for a specified period of time. |
| SqlExecute | Executes a SQL command |
| SvnCheckout | Checkout files from Subversion |
| SvnClient | Subversion Client |
| SvnCommit | Commit files to Subversion |
| SvnExport | Export files from Subversion |
| SvnInfo | Get Subversion information for a file or directory. |
| SvnUpdate | Update files from Subversion |
| SvnVersion | Get Subversion revision number of a local copy |
| TaskSchema | Generates a XSD schema of the MSBuild tasks in an assembly. |
| Time | Gets the current date and time. |
| Unzip | Unzip a file to a target directory. |
| Version | Increments a four-part version number stored in a text file |
| VssAdd | Adds files to a Visual SourceSafe database. |
| VssCheckin | Checks in files to a Visual SourceSafe database. |
| VssCheckout | Checks out files from a Visual SourceSafe database. |
| VssClean | Removes Visual SourceSafe binding information and status files from a Visual Studio solution tree. |
| VssDiff | Generates a diff between two versions of an item in a Visual SourceSafe database. |
| VssGet | Gets the latest version of a file or project from a Visual SourceSafe database. |
| VssHistory | Generates an XML file containing the history of an item in a Visual SourceSafe database between two dates or labels. |
| VssLabel | Labels an item in a Visual SourceSafe database. |
| VssUndoCheckout | Cancels a checkout of an item from a Visual SourceSafe database. |
| WebDirectoryCreate | Creates a new web directory on a local or remote machine. |
| WebDirectoryDelete | Deletes a web directory on a local or remote machine |
| WebDownload | Downloads a resource with the specified URI to a local file. |
| XmlRead | Reads a value from a XML document using a XPath. |
| XmlWrite | Updates a XML document using a XPath. |
| Xslt | Merge and transform a set of xml files. |
| Zip | Create a zip file with the files specified. |
Join Project
Please join the MSBuild Community Tasks Project and help contribute in building the tasks.
http://msbuildtasks.tigris.org/
Download The Latest Release
The latest binaries, source and installer for Windows can be found in this directory of the Tigris file-sharing area.
Here is a code snippet that is equivalent to the windows API PathRelativePathTo as native c#. The function creates a relative path from one file or folder to another.
public class PathUtil
{
/// <summary>
/// Creates a relative path from one file
/// or folder to another.
/// </summary>
/// <param name="fromDirectory">
/// Contains the directory that defines the
/// start of the relative path.
/// </param>
/// <param name="toPath">
/// Contains the path that defines the
/// endpoint of the relative path.
/// </param>
/// <returns>
/// The relative path from the start
/// directory to the end path.
/// </returns>
/// <exception cref="ArgumentNullException"></exception>
public static string RelativePathTo(
string fromDirectory, string toPath)
{
if (fromDirectory == null)
throw new ArgumentNullException("fromDirectory");
if (toPath == null)
throw new ArgumentNullException("toPath");
bool isRooted = Path.IsPathRooted(fromDirectory)
&& Path.IsPathRooted(toPath);
if (isRooted)
{
bool isDifferentRoot = string.Compare(
Path.GetPathRoot(fromDirectory),
Path.GetPathRoot(toPath), true) != 0;
if (isDifferentRoot)
return toPath;
}
StringCollection relativePath = new StringCollection();
string[] fromDirectories = fromDirectory.Split(
Path.DirectorySeparatorChar);
string[] toDirectories = toPath.Split(
Path.DirectorySeparatorChar);
int length = Math.Min(
fromDirectories.Length,
toDirectories.Length);
int lastCommonRoot = -1;
// find common root
for (int x = 0; x < length; x++)
{
if (string.Compare(fromDirectories[x],
toDirectories[x], true) != 0)
break;
lastCommonRoot = x;
}
if (lastCommonRoot == -1)
return toPath;
// add relative folders in from path
for (int x = lastCommonRoot + 1; x < fromDirectories.Length; x++)
if (fromDirectories[x].Length > 0)
relativePath.Add("..");
// add to folders to path
for (int x = lastCommonRoot + 1; x < toDirectories.Length; x++)
relativePath.Add(toDirectories[x]);
// create relative path
string[] relativeParts = new string[relativePath.Count];
relativePath.CopyTo(relativeParts, 0);
string newPath = string.Join(
Path.DirectorySeparatorChar.ToString(),
relativeParts);
return newPath;
}
}
The MSBuild Community Tasks Project has released the first version of tasks. The following is a sample build project that uses the SvnVersion, AssemblyInfo, NDoc and Zip tasks to create a release.
Import Targets
The first thing that needs to be done in the build file is to import the MSBuild.Community.Tasks.Targets file that defines the available tasks. If you use the msi installer to install the MSBuild Community Tasks, you can use the path "$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets".
Version Target
The first target in the sample file is the Version target. The version target is used to update the latest version number. First the SvnVersion task is used to get the latest Revision number from the local working subversion repository. SvnVersion outputs the Revision to the Revision property.
Next the target uses the AssemblyInfo task to generate an AssemblyInfo.cs file with the attributes specified.
Compile Target
The compile target calls msbuild to compile the solution in release mode. The MSBuild target will compile the solution the exact same way Visual Studio will.
Documentation Target
To create help for the project, there is the documentation target. In the documentation target, the NDoc task is used to compile a HTML Help project. To use the NDoc task, you must have NDoc 1.3.1 installed.
The generated HTML Help file is then moved to the documentation folder and the temp files are cleaned up.
Zip Target
The zip target is used to package up the whole project into a zip file. Zip target uses the Zip task to create the zip. The files included in the zip are selected by the ItemGroup ZipFiles.
Sample Master.proj File
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<Major>1</Major>
<Minor>0</Minor>
<Build>0</Build>
<Revision>0</Revision>
</PropertyGroup>
<ItemGroup>
<DefaultExclude Include="**\.svn\**" />
<DefaultExclude Include="**\bin\**" />
<DefaultExclude Include="**\obj\**" />
<DefaultExclude Include="**\Release\**" />
<DefaultExclude Include="**\Debug\**" />
<DefaultExclude Include="**\Test\**" />
<DefaultExclude Include="**\TestResults\**" />
<DefaultExclude Include="**\doc\**" />
<DefaultExclude Include="**\www\**" />
<DefaultExclude Include="**\*.user" />
<DefaultExclude Include="**\*.suo" />
<DefaultExclude Include="**\*.zip" />
<DefaultExclude Include="**\*.txt" />
</ItemGroup>
<ItemGroup>
<ZipFiles Include="**\*.*" Exclude="@(DefaultExclude)" />
</ItemGroup>
<Target Name="Version">
<SvnVersion LocalPath="$(MSBuildProjectDirectory)">
<Output TaskParameter="Revision" PropertyName="Revision" />
</SvnVersion>
<Message Text="Version: $(Major).$(Minor).$(Build).$(Revision)"/>
<AssemblyInfo CodeLanguage="CS"
OutputFile="Source\MSBuild.Community.Tasks\Properties\AssemblyInfo.cs"
AssemblyTitle="MSBuild Community Tasks"
AssemblyDescription="Collection MSBuild Tasks"
AssemblyCompany="http://msbuildtasks.tigris.org/"
AssemblyProduct="MSBuild.Community.Tasks"
AssemblyCopyright="Copyright © Paul Welter 2005"
ComVisible="false"
CLSCompliant="true"
Guid="d038566a-1937-478a-b5c5-b79c4afb253d"
AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)"
AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)"
Condition="$(Revision) != '0' "/>
</Target>
<Target Name="Compile" DependsOnTargets="Version">
<MSBuild Projects="Source\MSBuild.Community.Tasks.sln"
Properties="Configuration=Release" />
</Target>
<Target Name="Documentation" DependsOnTargets="Compile">
<NDoc Documenter="MSDN"
ProjectFilePath="Documentation\MSBuild.Community.Tasks.ndoc" />
<Copy SourceFiles="doc\MSBuild Community Tasks.chm"
DestinationFiles="Documentation\MSBuild.Community.Tasks.chm" />
<RemoveDir Directories="doc" />
</Target>
<Target Name="Zip" DependsOnTargets="Documentation">
<Zip Files="@(ZipFiles)"
ZipFileName="MSBuild.Community.Tasks.v$(Major).$(Minor).$(Build).$(Revision).zip" />
</Target>
<Target Name="Build" DependsOnTargets="Zip">
<Message Text="CodeSmith Build Complete"/>
</Target>
</Project>
I hope this sample will help in creating build files for your project.
~ Paul