<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Subsonic]]></title>
  <link href="http://subsonic.github.io/atom.xml" rel="self"/>
  <link href="http://subsonic.github.io/"/>
  <updated>2014-01-31T17:33:32-08:00</updated>
  <id>http://subsonic.github.io/</id>
  <author>
    <name><![CDATA[Rob Conery]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  
  <entry>
    <title type="html"><![CDATA[BatchQuery]]></title>
    <link href="http://subsonic.github.io/2012/02/27/batchquery/"/>
    <updated>2012-02-27T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2012/02/27/batchquery</id>
    <content type="html"><![CDATA[<h1>BatchQuery</h1>

<h2>Summary== Sometimes you have a routine that needs to make multiple calls to a database, which can be a bit of a drain on resources if you're opening/closing connections each time. This can happen when running multiple pass-through queries (UPDATES, INSERTS, DELETES) or if you need multiple different result sets.  BatchQuery can help in this regard - allowing you to execute multiple pass-throughs in a single transation or as a single statement. You can also execute SELECTs using multiple result sets.  ==Considerations== Sometimes it's not a good idea to return multiple result sets, or to execute multiple queries, using a single connection. This section discusses some things to consider.  If you batch together multiple calls into a single SQL statement, you can inadvertantly hold open a connection to your database for longer than you desire. This can end up in optimistic locking problems, or, if you're using something like SQLite, can lockup your entire database, causing issues for your application.  Finally, some providers don't allow you to use multiple result sets (called MARS). You should find out from your provider if it supports multiple return sets.  In addition, concurrency issues can creep up if the calls are not executed fast enough. Use this feature with caution.  ==Creating a Batch Query== To create BatchQueury, you need to create a provider (which is a glorified connection string wrapper) and then a BatchQuery:var provider=ProviderFactory.GetProvider("Northwind"); var batch=new BatchQuery(provider);  ==Executing Multiple Selects</h2>

<p>Once you have created your BatchQuery, you can now &quot;queue&quot; the queries you want to execute in one call. The BatchQuery will translate each query into a single SQL statement, executed with one command:<br>
var provider=ProviderFactory.GetProvider(&quot;Northwind&quot;); var batch=new BatchQuery(provider);  var query1=from p in db.Products            where p.ProductID</p>

<h2>1            select p; batch.Queue(query1);  var query2=from p in db.Products            where p.ProductID</h2>

<p>2            select p; batch.Queue(query2);  using(var rdr=batch.ExecuteReader()){         if(rdr.Read()){        //query1 results     }     rdr.MoveNext();     if(rdr.Read()){        //query2 results     } }  You can queue IQueryable or 
.  </p>

<h2>Executing Multiple Pass-through Queries== There are 2 ways to do this - with a transaction or without.   ===Using a Transaction=</h2>

<p>Probably the best way to execute multiple updates at once is to use a transaction to be sure that every update goes through. To do this, work up your query and use &quot;QueueForTransaction()&quot;:<br>
var provider=ProviderFactory.GetProvider(&quot;Northwind&quot;); var batch=new BatchQuery(provider);  var query1= new SubSonic.Query.Update<Product>(provider)            .Set(x =&gt; x.CategoryID </p>

<h2> 5)            .Set(x => x.UnitPrice == 100)            .Where(x => x.ProductID == 1);  batch.QueueForTransaction(query1);  var query2= new SubSonic.Query.Update<Product>(provider)            .Set(x => x.CategoryID == 1)            .Set(x => x.UnitPrice == 200)            .Where(x => x.ProductID == 2);  batch.QueueForTransaction(query2);  //execute transaction batch.ExecuteTransaction();  ===Using a Single SQL Statement=</h2>

<p>You can write the same queries above, however insteading of using &quot;QueueForTransaction&quot; you can just use &quot;Queue&quot; and then when it comes to execution, just use &quot;Execute()&quot;. This will produce the following SQL:<br>
UPDATE [dbo].[Products]  SET [dbo].[Products].[CategoryID]=5, [dbo].[Products].[UnitPrice ]=100, WHERE [dbo].[Products].[ProductID ]=1;  UPDATE [dbo].[Products]  SET [dbo].[Products].[CategoryID]=1, [dbo].[Products].[UnitPrice ]=200, WHERE [dbo].[Products].[ProductID ]=2</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Distinct]]></title>
    <link href="http://subsonic.github.io/2011/11/03/distinct/"/>
    <updated>2011-11-03T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2011/11/03/distinct</id>
    <content type="html"><![CDATA[<h1>Distinct</h1>

<p>Distinct is used by appending the &quot;Distinct()&quot; method on a query:[Test] public void SqlQuery<em>when</em>setting<em>distinct</em>it<em>should</em>set<em>IsDistinct() {  SubSonic.SqlQuery query= new    Select(Product.SupplierIDColumn).From<Product>().Distinct();  Assert.IsTrue(query.IsDistinct); }  [Test] public void SqlQuery</em>should<em>handle</em>distinct() {  ProductCollection select = new    Select(Product.SupplierIDColumn).From<Product>().Distinct()   .ExecuteAsCollection<ProductCollection>();   Assert.AreEqual(29, select.Count);  }  [Test] public void SqlQuery<em>GetRecordCount</em>should<em>handle</em>distinct() {  int select = new Select(Product.SupplierIDColumn)   .From<Product>().Distinct()   .GetRecordCount();   Assert.AreEqual(29, select); }   Hate to say this, but I have seen this misstated MANY times.  The SubSonic SqlQuery object does NOT have a Distinct method in it. It NEVER has.  Even with the release of 3.x it does not have a Distinct method.  The old Query object did but not the SqlQuery object. Unless someone you work with wrote one.  Which is easy enough to do.  I have done that myself.  Download the latest source and you will see, the SqlQuery object does not have this functionality, there are many other short comings of the SqlQuery object that I won&#39;t get into, but if you know enough about it, you can write your own methods to overcome its faults.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Supported Databases]]></title>
    <link href="http://subsonic.github.io/2010/12/23/supported_databases/"/>
    <updated>2010-12-23T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/12/23/supported_databases</id>
    <content type="html"><![CDATA[<h1>Supported Databases</h1>

<h2>SubSonic 2.x== Subsonic 2.2 Currently supports 5 main database engines: *SQL Server (2000 through 2008) *MySQL (5.0+) with special support for InnoDB *Oracle - although we've had reports of some issues with Foreign Keys and Stored Procedures *SQL CE (Compact Edition) *SQLite  We develop everything using SQL Server 2005, so you might fight an optimal experience using this with SQL.  ==SubSonic 3.0== ===Currently supported=</h2>

<p>SubSonic supports and has templates for:  *SQL Server (2000-2008) *MySQL (5.0 +) *SQLite *Oracle support through ODP.NET is currently in development. You can get the latest version of the SubSonic core from 
. The templates are also available 
. Please post details of any issues or questions to the 
 is currently in development. You can get the latest version of the SubSonic core from 
. The templates are also available 
. Please post details of any issues or questions to the 
.  </p>

<h2>=What about other databases?=</h2>

<p>Our goal with SubSonic 3.0 was to unhinge the core from any dependency on a specific engine. We do this by using System.Data.Common - which is part of Microsoft&#39;s DataFactory stuff. Most major databases have a provider which works with System.Data.Common - including:  *PostGres *SQL CE *VistaDB  SubSonic will execute queries against these databases, however we&#39;re still working on creating a meaningful set of templates for each.  It&#39;s important to understand that SubSonic 3.0 talks to the database when creating your Data Access stuff using our 
, SQL Server will return a completely different result set than MySQL. This is supposed to be a standard - but there are obviously deviations with each provider.  Our SQL Server templates query INFORMATION_SCHEMA - an ANSI-standard set of system views that each provider should offer for each database. However MySQL doesn&#39;t implement them in the same way SQL Server does - so we can&#39;t provide a &quot;single template fits all&quot; scenario.  It&#39;s our hope that our 
 - so if you take the time to create a nice set of templates - please add to our wiki!</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[3.0 Summary]]></title>
    <link href="http://subsonic.github.io/2010/10/26/30_summary/"/>
    <updated>2010-10-26T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2010/10/26/30_summary</id>
    <content type="html"><![CDATA[<h1>3.0 Summary</h1>

<h2>Summary==  SubSonic 3.0 is the latest version of SubSonic and was released in June of 2009. Work on SubSonic 3.0 lasted close to a year, and revolved mostly around supporting Language-integrated Query, also known as LINQ.  The focus of SubSonic 3.0 is to provide tools, not guidance or an overall mindset/approach. There are a number of things in SubSonic that allow you to move faster while applying whatever patterning floats your boat. We're not as complete as NHibernate, but you'll work faster with less concept count. We're not as deep as Linq to SQL, but you can use our stuff on most databases.  ==Linq</h2>

<p>SubSonic 3.0 supports Linq with a core Expression Parser that turns System.Linq.Expressions into SQL. In addition, our 2.0 Query Tool (now called 
 can use Lambda expressions to simplify some tasks.  All of the templates we use build on top of our core parsers and query tools, and you can 
 of these quite easily.  </p>

<h2>Simple Query Tool</h2>

<p>The 
&quot; method that will execute a query and load an object for you.  </p>

<h2>Utilities</h2>

<p>SubSonic also comes with a number of utility methods expressed as Extension Methods. This is SubSonic&#39;s 
 and has a number of things to save you time, including File IO, string methods, date math, number utilities, and Object parsing.  </p>

<h2>API Reference</h2>

<p>This is a list of all the public 
 assembly. The details have not been written in most cases - feel free to contribute. This is intended as an aid to navigating the documentation and linking code examples together.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[3.0 Transactions]]></title>
    <link href="http://subsonic.github.io/2010/06/21/30_transactions/"/>
    <updated>2010-06-21T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2010/06/21/30_transactions</id>
    <content type="html"><![CDATA[<h1>3.0 Transactions</h1>

<h2>Summary== Transactions are a core need for many application developers and involve executing a set of directions in a "all or nothing" manner - meaning that if one instruction fails - the whole thing fails.  ==Considerations== The easiest thing to do is to use System.Transactions to wrap a "TransactionScope" around whatever it is you're doing. To make this work, however, you'll need to have the Distributed Transaction Coordinator (DTC) running on your server.  You can get around this, however, by "suppressing" the "elevation" to DTC (which ADO will do for you if it's confused as to what's needed) by using our "SharedDbConnectionScope" (see below).  ==Example of Using Scope== Executing Transactions using SubSonic is a matter of wrapping a scope around a section of code (using System.Transactions):using (SharedDbConnectionScope sharedConnectionScope = new SharedDbConnectionScope()){    using (TransactionScope ts = new TransactionScope())    {        Product p = new Product.SingleOrDefault(x=>x.ProductID==1);        p.Title = "new title";         Product p2 = new Product.SingleOrDefault(x=>x.ProductID==2);        p.Title = "another new title";         // ...        p.Save();        p2.Save();        ts.Complete();   } }  ==Using Built-in Methods</h2>

<p>There are other ways of working with transactions in SubSonic, and if you&#39;re worried about using the DTC then you might want to consider using the built in tools, specifically the 
.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Linq IRepository]]></title>
    <link href="http://subsonic.github.io/2010/06/11/linq_irepository/"/>
    <updated>2010-06-11T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2010/06/11/linq_irepository</id>
    <content type="html"><![CDATA[<h1>Linq IRepository</h1>

<h2>Summary</h2>

<p>For testability, SubSonic 3.0 now includes an IRepository
interface that you can extend via T4 Templates. The Repository is pretty straightforward:<br>
public interface IRepository<T>     {         IQueryable<T> GetAll();         PagedList<T> GetPaged(Expression<Func<T, bool>&gt; orderBy, int pageIndex, int pageSize);         IQueryable<T> Find(Expression<Func<T, bool>&gt; expression);         void Add(T item);         int Update(T item);         int Delete(T item);         int Delete(object key);         int Delete(Expression<Func<T, bool>&gt; expression);         T GetByKey(object key);     }  This interface is implemented in SubSonic.Core.dll.  You will find this interface as well as an implementation - SubSonicRepository
- in the SubSonic.Repository namespace.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Setting up SubSonic 3.0]]></title>
    <link href="http://subsonic.github.io/2010/05/12/setting_up_subsonic_30/"/>
    <updated>2010-05-12T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2010/05/12/setting_up_subsonic_30</id>
    <content type="html"><![CDATA[<h1>Setting up SubSonic 3.0</h1>

<h2>Screencast</h2>

<p>Setting up 
 and you&#39;re good to go. Here&#39;s a walkthrough:  <ag> SubSonic3_5MinuteDemo.flv </ag>  </p>

<h2>Walkthrough</h2>

<p>Setting up 
 in your project is meant to be silly simple. Here are the steps, in order:  #Create a new project in Visual Studio 2008 #Add a connection string to your Web/App.config, give it a name, and point it to a valid database #Grab the folder containing the 
 and locate the one that named &quot;_Settings&quot;. Open it up in Notepad and set the value for &quot;ConnectionStringName&quot; to the name of the connection string you just made. #Drop the folder with the 
 templates into your project. Visual Studio 2008 will see these and execute the template code, creating your classes #You&#39;re done - go have a Kabob.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Using ActiveRecord]]></title>
    <link href="http://subsonic.github.io/2010/04/24/using_activerecord/"/>
    <updated>2010-04-24T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2010/04/24/using_activerecord</id>
    <content type="html"><![CDATA[<h1>Using ActiveRecord</h1>

<h2>Summary</h2>

<p>is the simplest, easiest way to work with your data and your database. The pattern is that each instance you work with is, literally, a row of data in your database. This means that each object type can be thought of as a table in your database.  Many developers don&#39;t like to work this &quot;closely&quot; with their database - however others view this kind of thing as absolutely ideal - removing the object-oriented &quot;impedance mismatch&quot; in favor of working with a thin database abstraction.  SubSonic&#39;s approach to 
 is to give you what you need, then get out of your way. You&#39;ll find you have the ability to use Linq and simple, easy code-generation to get your data quick and simple-like.  </p>

<h2>Setup</h2>

<p>Setting up SubSonic&#39;s 
 is pretty simple and involves four steps.  </p>

<h2>=Add a Reference to SubSonic=</h2>

<p>Download and extract 
 in a folder like this.  Then inside your project right-click the &quot;Reference&quot; folder, and select Add Reference. Browse to find the SubSonic.Core.dll file and include it.  </p>

<h2>=Add a Connection String=== In order to work with your database you'll need a connection string that is located in your project's app.config or web.config.  If you have a seperate project for your data access code, you may need to create a new app.config in the root of the project.  If you're working with a provider other than SQL Server (such as SQLite), you'll need to specify which one by changing the "providerName" attribute value:<configuration>     ...     <connectionStrings>       <add name="Northwind"           connectionString="server=.\SQLExpress;database=SubSonic;integrated security=true;"           providerName="System.Data.SqlClient"/>       <add name="NorthwindSQLite"           connectionString="Data Source=C:\my.db"           providerName="System.Data.SQLite"/>       <add name="NorthwindMySql"           connectionString="server=localhost;database=northwind;user id=root; password="           providerName="MySql.Data.MySqlClient"/>    </connectionstrings>   </configuration>  ===Set The Connection In The Templates=</h2>

<p>Look in the Templates folder in the files extracted earlier.  The 
 Templates that create the classes you&#39;re going to work with need to know what your connection string is. To set this, open up the file called &quot;Settings.ttinclude&quot;. Below the @import statements, you&#39;ll see three string values you&#39;ll need to change:<br>
const string Namespace = &quot;Northwind.Data&quot;;     const string ConnectionStringName = &quot;Northwind&quot;;          //This is the name of your database and is used in naming     //the repository. By default we set it to the connection string name     const string DatabaseName = &quot;Northwind&quot;;  &quot;Namespace&quot; refers to the namespace that the generated subsonic code will be placed under.<br>
namespace Northwind.Data   {     public class YourEntity     {     ...     }   }  You need to fill out &quot;ConnectionStringName&quot; with the connection string value that you placed in your app.config or web.config file earlier.  This tells SubSonic which connection to use in the DB.  Change the &quot;DatabaseName&quot; value to the name of the database specified in the connection string.  The include directive in all *.tt files need to match your database. The ActiveRecord.tt on GitHub master, as of this writing, points to MySQL.ttinclude.<br>
// other values: MySQL.ttinclude, SQLite.ttinclude &lt;#@ include file=&quot;SQLServer.ttinclude&quot; #&gt;  </p>

<h2>=Add the T4 Templates To Your Project=== After you've set the settings above, just drag into your project. Whenever Visual Studio 2008 sees a "tt" file, it will automatically execute it - so you don't have to do anything, it will just run.  List of files to drag:  * ActiveRecord.tt * Context.tt * Settings.ttinclude * SQLServer.ttinclude OR MySQL.ttinclude OR SQLite.ttinclude * StoredProcedures.tt - optional, add if you will invoke stored procedures * Structs.tt  If you make a change to your database, just right-click the ActiveRecord.tt, Context.tt and Structs.tt files (CTRL+Click to select all *.tt files) and select "Run Custom Tool" and this will execute them again.  If you have any errors at this point, you need to check your settings in the prior step.  ==Querying</h2>

<p>The whole point of using ActiveRecord is to make querying easy. Here are some examples from our unit tests:<br>
//find a single product by ID var product = Product.SingleOrDefault(x =&gt; x.ProductID </p>

<h2> 1);  //get a list of products based on some criteria var products = Product.Find(x => x.ProductID <= 10);  //get a list of server-side paged products var products = Product.GetPaged(0,10);  //query using Linq var products = from p in Product.All()           join od in OrderDetail.All() on p.ProductID equals od.ProductID           select p;  You'll notice that we've departed a bit from the way SubSonic 2.0 works (as well as other ActiveRecord libraries). Most other libraries use the constructor to pass in the key or name/value pair to find a single record. This can lead to some confusion if there is no record as your object will not be null (as it should be).  For this reason we use a Factory to get single values - as you can see above.  ==Testing</h2>

<p>Testing with ActiveRecord can be a major pain because it lives &quot;so close&quot; to your database. Rails uses the concept of a Test Database for this - basically saying &quot;get over it&quot; with respect to involving your DB in your unit tests. This can work fine for you - if you want to use a test database you can and ActiveRecord will work fine.  To do this, simply set your connection string in your test project (in the App.config) to point to your test database, and you&#39;re good to go.  If you want to have speedier tests with less of a chance of failure due to bad data or connection issues - you can work with SubSonic&#39;s built-in testing (for ActiveRecord). There&#39;s nothing you need to do other than use the connection string &quot;Test&quot; in your test project:<br>
<add name="Northwind"           connectionString="Test"           providerName="System.Data.SqlClient"/>  This will tell SubSonic to use a Faked up repository (called TestRepository) which works with a fake set of data. You can set this up as you like using Setup():<br>
//add 100 products to the fake repository Product.Setup(100); //make sure they&#39;re there! Assert.Equal(100,Product.All().Count());  You can also send in the list you want to work with if you want to mock up specific objects. See the constructor overloads for an example.  You will be working against an in-memory List
at this point (based on Setup()), so saving/deleting/editing will add/delete objects in the same way you would see with a database.  </p>

<h2>Changing generated table class names in SubSonic 3</h2>

<p>Subsonic 2.0 had a feature that was modifiable via the webconfig called 
stripTableText that allowed you to modify the generated class names used by SubSonic.  While not instantly obvious doing the same thing is even simpler and more powerful in subsonic 3 simply by editing the 
Settings.ttinclude file.  The standard empty 
Settings.ttinclude file&#39;s 
CleanUp method: 
string CleanUp(string tableName){   string result=tableName;         //strip blanks   result=result.Replace(&quot; &quot;,&quot;&quot;);         //put your logic here...         return result; }  An simple example of the file edited to change 
 into </p>

<p>string CleanUp(string tableName){   string result=tableName;         //strip blanks   result=result.Replace(&quot; &quot;,&quot;&quot;);    //strip the phrase &quot;tbl&quot;   result=result.Replace(&quot;tbl&quot;,&quot;&quot;);         return result; }  You soon see the simple power for table name manipulation the templates allow.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Using SimpleRepository]]></title>
    <link href="http://subsonic.github.io/2010/03/16/using_simplerepository/"/>
    <updated>2010-03-16T00:00:00-07:00</updated>
    <id>http://subsonic.github.io/2010/03/16/using_simplerepository</id>
    <content type="html"><![CDATA[<h1>Using SimpleRepository</h1>

<h2>Summary</h2>

<p>Most data access libraries work from &quot;the database outward&quot; - meaning that one way or another your database tables are represented as objects in your application. This can work in many cases, but relational theory does not align with object-oriented programming, and you get into a hole which is commonly referred to as &quot;the impedance mismatch&quot;.  Many people like to work with classes and don&#39;t want to worry about the database implementation - freeing them to work as they want to work without opening up a database designer in order to model their classes. The objects they create a free of base classes and exist on their own, as plain-old CLR objects (also known as POCOs).  If you&#39;re one of these people and you don&#39;t particularly care about the database structure - the 
 is for you.  </p>

<h2>Screencast== Couldn't help myself... love to make these things... <ag> subsonic_migrations.flv </ag>  ==Setup</h2>

<p>Setting up the 
 is part of the fun of using it in that all that&#39;s involved is adding SubSonic and a connection string. The focus is getting completely out of your way.  </p>

<h2>=Add a Reference to SubSonic=== This part is pretty simple: right-click your project, Add Reference, and Browse to find the SubSonic 3.0 dll.  ===Add a Connection String=== In order to work with your database you'll need a connection string. If you're working with a provider other than SQL Server (such as SQLite), you'll need to specify which one using "providerName":<add name="Northwind"           connectionString="server=.\SQLExpress;database=SubSonic;integrated security=true;"           providerName="System.Data.SqlClient"/>      <add name="NorthwindSQLite"           connectionString="Data Source=C:\my.db"           providerName="System.Data.SQLite"/>     <add name="NorthwindMySql"           connectionString="server=localhost;database=northwind;user id=root; password="           providerName="MySql.Data.MySqlClient"/>  You're done!  ==Auto Migrations</h2>

<p>One of the fun things about working with Rails is that you can build your DB from code and focus on your app. Many developers have found this very freeing (myself included). One drawback to it, however, was that you needed to learn the code for the Migration, and you needed to know how it worked. This, to me, was not a show-stopper in the least but I always wished Rails would &quot;just know&quot; and migrate stuff for me.  This is what I&#39;m trying to do with Auto Migrations using SubSonic. The goal here is if you set a flag in the SimpleRepository constructor, you can tell it to migrate your model for you - automatically creating and synchronizing your database for you.  The key to this is setting the proper options in the constructor:<br>
var repository=new SimpleRepository(SimpleRepositoryOptions.RunMigrations);  Setting this to RunMigrations tells SubSonic to migrate your model object to the database whenever you try to access the database or save data.  </p>

<h2>=Migration Example=</h2>

<p>Suppose you have an object called Post: 
public class Post{    public Guid ID {get; set;}    public string Title {get; set;}    public string Body{get; set;} }  When you use this object with the SimpleRepository, assuming you&#39;ve set the options to RunMigrations, it will create the tables you need: 
//create a new repository for BlogDB database, turning migrations on var repo=new SimpleRepository(&quot;BlogDB&quot;,SimpleRepositoryOptions.RunMigrations); var post=repo.Single<Post>(x=&gt;x.Title=&quot;My Title&quot;);   In this example there is no post with this title, since there is no Posts table. The Single() method, however, will run the migration for you and will create the table - so there will be no error.  When run for the first time, the following SQL will be executed prior to the SELECT: 
CREATE TABLE <a href="%5BID%5D%20uniqueidentifier%20NOT%20NULL%20PRIMARY%20KEY,%20%20%20%5BTitle%5D%20nvarchar(255">Posts</a> NOT NULL,   [Body] nvarchar(255) NOT NULL, ); ALTER TABLE [Posts] ADD CONSTRAINT PK<em>Posts</em>Key PRIMARY KEY([ID])&quot;;  Notice that the table name is pluralized (by convention), the &quot;ID&quot; property is selected as the key (again by convention), and the strings are defaulted to a length of 255.  You can change the way SubSonic creates the table by using a small set of attributes - specifically:  *
: If you call a column ID or Key or [ClassName]ID  no matter its type  that will be your Primary Key. If you have other things in mind you can use a primary key attribute (SubSonicPrimaryKey) and well use that column. *
: There are two ways to tell SubSonic how to handle this  both using attributes. The first is SubSonicStringLength(int length) and the second is SubSonicLongString which sets to nvarchar(MAX) or LONGTEXT  depending on your provider. *
: The default is not null, but you can change this by making your property a nullable type. *
: The default is a Precision of 10 and a scale of 2 but you can change that with the SubSonicNumericPrecision(int precision, int scale) attribute. *
: you can ignore generation of a property by using SubSonicIgnore attribute.<br>
Updating Your Model Starting out is the easy part, but as you develop you will be changing and removing properties from your class. SubSonic will do its best to keep up with you.  For example, let&#39;s say you&#39;ve added a PublishDate to your Post class: 
public class Post{    public Guid ID {get; set;}    public string Title {get; set;}    public string Body{get; set;}    public DateTime PublishDate {get;set;} }  When you next Save/Find/Get data using the SimpleRepository, the following command will be sent along first:<br>
ALTER TABLE [Posts] ADD DateTime datetime NOT NULL CONSTRAINT DF<em>Posts</em>PublishDate DEFAULT (&#39;01/01/0001&#39;); UPDATE SubSonicTests SET PublishDate =&#39;01/01/0001&#39;;  There are a few things happening here. The first is that the column is added for you (with NOT NULL - which you can change by using DateTime?). The second is that a default is put in place for you (using DateTime.MinValue) - a non-null column should have a default value in general (our convention).  The UPDATE statement is there to deal with existing records that might be in the database already - setting their value to the default (for other providers like SQLite and MySQL).  Continuing on - removing a property will result in the column being dropped from the database.  </p>

<h2>Querying</h2>

<p>You can query your database through the repository quite easily, even using Linq if you like:<br>
var repo=new SimpleRepository(SimpleRepositoryOptions.RunMigrations);  //see if a record exists bool exists=repo.Exists<Post>(x=&gt;x.Title</p>

<h2>"My Title");  //use IQueryable var qry=from p in repo.All<Post>()         where p.Title=="My Title"         select p;  //get a post var post=repo.Single<Post>(x=>x.Title=="My Title"); var post=repo.Single<Post>(key);  //a lot of posts var posts=repo.Find<Post>(x=>x.Title.StartsWith("M"));  //a PagedList of posts - using 10 per page var posts=repo.GetPaged<Post>(0,10); //sort by title var posts=repo.GetPaged<Post>("Title",0,10);  //add a post var newKey=repo.Add(post);  //add a lot of posts - using a transaction IEnumerable<Post> posts=GetABunchOfNewPosts(); repo.AddMany(posts);  //update a post repo.Update(post);  //update a bunch of posts in a transaction IEnumerable<Post> posts=GetABunchOfNewPosts(); repo.UpdateMany(posts);  //delete a post repo.Delete<Post>(key);  //delete a lot of posts repo. DeleteMany <Post>(x=>x.Title.StartsWith("M"));  //delete posts using a transaction IEnumerable<Post> posts=GetABunchOfNewPosts(); repo.DeleteMany(posts);  ==Testing</h2>

<p>Testing with SimpleRepository is very simple as it inherits from SubSonic.Repository.IRepository. If you follow an injection pattern whereby you pass in an IRepository, then you can use your favorite mocking tool or create a fake repository to query against.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[The 5 Minute Demo]]></title>
    <link href="http://subsonic.github.io/2010/02/21/the_5_minute_demo/"/>
    <updated>2010-02-21T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/02/21/the_5_minute_demo</id>
    <content type="html"><![CDATA[<h1>The 5 Minute Demo</h1>

<h2>Summary</h2>

<p>This demo shows off ActiveRecord - a very easy way to work with SubSonic. Don&#39;t miss the 
, however!  SubSonic is all about helping you do what you need to do with the least amount of friction. No need to overthink things anymore - just build your app.  <ag> SubSonic3_5MinuteDemo.flv </ag></p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[T4 Templates]]></title>
    <link href="http://subsonic.github.io/2010/02/21/t4_templates/"/>
    <updated>2010-02-21T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/02/21/t4_templates</id>
    <content type="html"><![CDATA[<h1>T4 Templates</h1>

<h2><a href="">Summary</a></h2>

<p>T4 stands for &quot;Text Template Transformation Toolkit&quot; and, simply put, is code generation inside Visual Studio.  It&#39;s very easy to work with if you&#39;re familiar with scripting ASP.NET pages - except that it works with a  syntax rather than . Another thing to remember is that you&#39;re working with Visual Studio - not your project. The templates run in a completely different AppDomain - so you can&#39;t use your project&#39;s configuration without doing a little gymnastics.  To get you started, I made a screencast - complete with some music from Rush:  <ag> t4.flv </ag>    </p>

<h2>= Troubleshooting =</h2>

<p>Having trouble with your t4 templates? Have a look at the 
 to see the most common causes.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Submit Patch]]></title>
    <link href="http://subsonic.github.io/2010/02/21/submit_patch/"/>
    <updated>2010-02-21T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/02/21/submit_patch</id>
    <content type="html"><![CDATA[<h1>Submit Patch</h1>

<h2>Summary== The Concept of "patching" is a little different with Github and Git. If you've never used Git before, you might need to brush up a bit on it. Once you do it, however, it's very, very simple and extremely helpful!  ==Getting to Know Github== This screencast will walk you through all you need to know to get working with Github and Git. It lasts about 10 minutes or so and you'll learn a bunch of new stuff!  <ag>git.flv</ag>  ==Github Issue Tracker Integration</h2>

<p>Additionally, you can follow the convention of appending &quot;Closes #1&quot; (where 1 is the issue number) to your Commit messages. Github will automatically mark that Issue as Resolved!  </p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Simple Repo 5 Minute Demo]]></title>
    <link href="http://subsonic.github.io/2010/02/21/simple_repo_5_minute_demo/"/>
    <updated>2010-02-21T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/02/21/simple_repo_5_minute_demo</id>
    <content type="html"><![CDATA[<h1>Simple Repo 5 Minute Demo</h1>

<h2>Summary</h2>

<p>There are a few ways to work with SubSonic 3.0. One of them is to tell it to get right out of your way - and that&#39;s the point of the 
.   Many times code generation and configuration get in your way. If all you want is a DLL and pot to cook your data in  - well this is for you.  </p>

<h2>Demo</h2>

<p><ag> SimpleRepo.flv </ag></p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Migrations]]></title>
    <link href="http://subsonic.github.io/2010/02/21/migrations/"/>
    <updated>2010-02-21T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/02/21/migrations</id>
    <content type="html"><![CDATA[<h1>Migrations</h1>

<h2>Summary</h2>

<p>This is for SubSonic 2.x Only Migrations help you design your database using code that you write. It&#39;s a Rails thing and a lot of people love it.  </p>

<h2>Give Shawn Oster Some Love== I laid the groundwork for Migrations a while ago, but didn't have the bandwidth to give it the love it deserved. Frankly I don't know if I was smart enough.  I asked Shawn Oster to help out and he took his massive swingin geek smarts and put together a pretty cool set of functionality.  So if you see Shawn at the local Denver Gamer Shop, setting up for the Monday Night D&D Showdown (LARP-fest), give him a wizardly high-five!  ==Video== <ag>subsonic_migrations.flv</ag>  ==The Code</h2>

<p>The Migration system works by basically &quot;sucking&quot; out the Migration classes from your project, reading in the code, and then executing it in a virtual compiler. This may seem complex, but it&#39;s actually pretty simple and at it&#39;s core is what we do to generate the code files anyway.  To create a Migration, you have to follow our Conventional system and create a class file, something like     001<em>Initial.cs  ... and place that class file into a folder called &quot;Migrations&quot; off the root of your project (you can override this directory convention - see below).  This class file must have one class (call it whatever you like), and it has to inherit from SubSonic.Migration:using System; using System.Collections.Generic; using System.Text; using SubSonic;  namespace MigrationSample.Migrations {      public class Migration001:Migration {     } }  Each &quot;Migration&quot; consists of changing from one version to another, either up or down. The code, therefore, follows this logic and offers two methods for you to tell the DB what to look like.  For the first example (001</em>Init), this is version one. The Up() method therefore is transitioning the DB from version 0 to version 1, so we need to put in some code to tell it what we want it to do: 
public override void Up() {              //Create the Records Table             TableSchema.Table records = CreateTableWithKey(&quot;Records&quot;);             records.AddColumn(&quot;RecordName&quot;);             records.AddColumn(&quot;GroupID&quot;, System.Data.DbType.Int32);             records.AddColumn(&quot;LabelID&quot;, System.Data.DbType.Int32);              AddSubSonicStateColumns(records);              //Create the Groups Table             TableSchema.Table groups = CreateTableWithKey(&quot;Groups&quot;);             groups.AddColumn(&quot;GroupName&quot;);             AddSubSonicStateColumns(groups);              //Link them             CreateForeignKey(groups.GetColumn(&quot;id&quot;), records.GetColumn(&quot;groupID&quot;));           }  For the Down() method, we need to reverse, exactly, everything we did with Up(): 
public override void Down() {             TableSchema.Table records = GetTable(&quot;records&quot;);             TableSchema.Table groups = GetTable(&quot;groups&quot;);              //drop the FK             DropForeignKey(groups.GetColumn(&quot;id&quot;), records.GetColumn(&quot;groupID&quot;));                          DropTable(&quot;Records&quot;);             DropTable(&quot;Groups&quot;);         } *Note: I&#39;m working on the syntax to drop the FK constraint. I know it&#39;s heavy.  If you needed to alter a column, you use:      AlterColumn(&quot;records&quot;, &quot;RecordName&quot;, System.Data.DbType.String, 800); You can change the column&#39;s length, type, name, and nullability if you need to. You can also remove a column from a table:      RemoveColumn(&quot;records&quot;, &quot;groupid&quot;);  </p>

<h2>Iterations</h2>

<p>If your client says to you &quot;hey great, you made a Records table - but you forgot Labels! You have labelID, where&#39;s labels!&quot; - it&#39;s time to write another Migration, and migrate from version 1 to version 2:  Following our convention, add another class file to the Migrations folder:     002_AddLabels  Next up, add the code to Up/Down our migration:<br>
namespace MigrationSample.Migrations {          public class Migration002:Migration {         public override void Up() {              //add the labels table             TableSchema.Table labels = CreateTableWithKey(&quot;Labels&quot;, &quot;labelID&quot;);             labels.AddColumn(&quot;LabelName&quot;);             AddSubSonicStateColumns(labels);               Execute(&quot;INSERT INTO Labels(labelname) VALUES(&#39;Capitol&#39;)&quot;);             Execute(&quot;INSERT INTO Labels(labelname) VALUES(&#39;Arista&#39;)&quot;);             Execute(&quot;INSERT INTO Labels(labelname) VALUES(&#39;Virgin&#39;)&quot;);              TableSchema.Table records = GetTable(&quot;records&quot;);             CreateForeignKey(labels.GetColumn(&quot;labelID&quot;), records.GetColumn(&quot;id&quot;));          }          public override void Down() {             TableSchema.Table records = GetTable(&quot;records&quot;);             TableSchema.Table labels = GetTable(&quot;labels&quot;);              //drop the FK             DropForeignKey(labels.GetColumn(&quot;labelID&quot;), records.GetColumn(&quot;id&quot;));             DropTable(&quot;labels&quot;);         }     } } Yes! Migrations also allow you to add data! I know that inline script is probably not what you had in mind ;) - I&#39;ll have this worked out by the time we go final with 2.1 (allowing you to use our query tool) but for now - the ability is there.  Now, to execute...     sonic.exe /migrate  You can set this up like you do with other SubCommander commands - please see the video for how to make this happen!  </p>

<h2>Comparisons== There are other things out there (like DB projects with VS) and I go into some of this in the video (nudge nudge). This isn't a versioning tool per se - it's a development tool. If you like scripts, more power to ya. Migrations take a little getting used to, that's for sure.  ==Caveats</h2>

<p>This stuff may still be a tad rough. We&#39;ve tested it a lot, but whenever you talk about tweaking DB schema and code... well there&#39;s a reason there&#39;s not many Migration solutions in .NET land right now :). Please be patient and help us to get this up to par.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Command line]]></title>
    <link href="http://subsonic.github.io/2010/02/21/command_line/"/>
    <updated>2010-02-21T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/02/21/command_line</id>
    <content type="html"><![CDATA[<h1>Command line</h1>

<h2>Summary== This is a walkthrough of how to setup Visual Studio to call our command-line tool, sonic.exe. This tool is designed to help you along in your day and hopefully do the heavy-lifting for you. Please note that with SubSonic 3.0, we're using T4 templates to do most of the code generation stuff here.  ==Configuration== SubCommander will always try and find a configuration file in its executing directory (Web.Config or App.Config). If it does, it will look for config information for itself there, and set itself up accordingly. You can override this by using the /config switch, and then telling it where it can find the config file:      sonic.exe generate /config "c:\myproject\App.config"   If you're working with a project and you want to use our generated code, just add an App.config file to the project, then you can run SubCommander in that directory.  ==Manual Configuration==  All of the config options can be passed in as switches ("/includeTableList table1, table2, table4" e.g.) to SubCommander. This is handy for when you want to use a BAT file.  ==Scripting Schema and Data==  You can script out your schema and data (and then version it in your favorite source control system) using SubCommander. Simply use the command "version" and tell SubCommander where to put the data:    sonic.exe version /out Scripts This will output a script file (.sql) to the local scripts directory of your project  ==Command Reference==  Here are the commands you can use currently with SubCommander:  *version:  Scripts out the schema/data of your db to file *scriptdata:  Scripts the data to file for your database *scriptschema:  Scripts your Database schema to file *generate:  Generates output code for tables, views, and SPs *generatetables: Generates output code for your tables *generateODS: Generates and ObjectDataSource controller for each table *generateviews:  Generates output code for your views *generatesps: Generates output code for your SPs  ==Screencast</h2>

<p><ag>SubCommander.flv</ag></p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Recent Changes]]></title>
    <link href="http://subsonic.github.io/2010/01/19/recent_changes/"/>
    <updated>2010-01-19T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/01/19/recent_changes</id>
    <content type="html"><![CDATA[<h1>Recent Changes</h1>

<p>One thing I noticed recently when working with Subsonic 3.0 and the T4 templates was that there was no way to detect if a stored procedure has nullable parameters.  After a bit of research I found this msdn article 
(?
.<em>?)\s{1}as\s{1}&quot;;             RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;             MatchCollection matches = Regex.Matches(procedureText, regex, options);             if (matches.Count &gt; 0 &amp;&amp; matches[0].Groups[&quot;Params&quot;] != null)             {                 Match match = matches[0];                 arguments = match.Groups[&quot;Params&quot;].ToString();                 argumentArray = Regex.Split(arguments, &quot;,&quot;);                 foreach (string sArgument in argumentArray)                 {                     MatchCollection paramMatches = Regex.Matches(sArgument, @&quot;(?
@\S</em>)&quot;, options);                     MatchCollection nullMatches = Regex.Matches(sArgument, @&quot;(?
=\s*)&quot;, options);                     if (paramMatches.Count &gt; 0 &amp;&amp; paramMatches[0].Groups[&quot;ParamName&quot;] != null)                     {                         bool isNullDefault = (nullMatches.Count &gt; 0 &amp;&amp; nullMatches[0].Groups[&quot;NullString&quot;] != null);                         parameterNullibility.Add(paramMatches[0].Groups[&quot;ParamName&quot;].ToString());                     }                 }             }             return parameterNullibility;         }   b. Change SPPArams  List
GetSPParams(string spName)         {             var result = new List
();             string[] restrictions = new string[3] { null, null, spName };             string procedureText;              procedureText = GetStoredProcedureText(spName);             List<string></string> nullableParams = this.GetNullableParams(procedureText);             using (SqlConnection conn = new SqlConnection(ConnectionString))             {                 conn.Open();                                 var sprocs = conn.GetSchema(&quot;ProcedureParameters&quot;, restrictions);                  using (SqlCommand cmd = new SqlCommand(spName, conn))                 {                     cmd.CommandType = CommandType.StoredProcedure;                     SqlCommandBuilder.DeriveParameters(cmd);                 }                 conn.Close();                 foreach (DataRow row in sprocs.Select(&quot;&quot;, &quot;ORDINAL<em>POSITION&quot;))                 {                     SPParam p = new SPParam();                     p.SysType = GetSysType(row[&quot;DATA</em>TYPE&quot;].ToString());                     p.DbType = GetDbType(row[&quot;DATA<em>TYPE&quot;].ToString()).ToString();                     p.Name = row[&quot;PARAMETER</em>NAME&quot;].ToString().Replace(&quot;@&quot;, &quot;&quot;);                     p.ParameterMode = GetParamDirection(row[&quot;PARAMETER<em>MODE&quot;].ToString()).ToString();                     p.CleanName = CleanUp(p.Name);                      if (nullableParams.Contains(row[&quot;PARAMETER</em>NAME&quot;].ToString()))                         p.Nullable = true;                     result.Add(p);                 }               }             return result;         }            2.  Inside Setting.ttinclude  a. Change SSParam class as follows    public class SPParam{         public string Name;         public string CleanName;         public string SysType;         public string DbType;         public string ParameterMode;         public bool Nullable;     }   b. Change ArgList property as follows.  public string ArgList{             get{                 StringBuilder sb=new StringBuilder();                 int loopCount=1;                 foreach(var par in Parameters){                                      if (par.Nullable)                         {                             if ( par.SysType.ToString() != &quot;string&quot; &amp;&amp; par.SysType.ToString() != &quot;byte[]&quot;)                             {                                 sb.AppendFormat(&quot;{0}{1} {2}&quot;, par.SysType, &quot;?&quot;,  par.CleanName);                             }                             else                             {                                  sb.AppendFormat(&quot;{0} {1}&quot;, par.SysType, par.CleanName);                             }                         }                         else                         {                             sb.AppendFormat(&quot;{0} {1}&quot;, par.SysType, par.CleanName);                         }                                          if(loopCount</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Simple Query Tool]]></title>
    <link href="http://subsonic.github.io/2010/01/17/simple_query_tool/"/>
    <updated>2010-01-17T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/01/17/simple_query_tool</id>
    <content type="html"><![CDATA[<h1>Simple Query Tool</h1>

<p>SubSonic comes with a variety of ways to talk to your database. Originally we had a query tool that was a little verbose and somewhat difficult to use. That has since been refined to use a &quot;fluent interface&quot; - which is the chaining of methods to be, essentially, human-readable.  These examples are specific to SubSonic 2 see 
;  Simple Select with typed columns 
int records = new Select(Product.ProductIDColumn, Product.ProductNameColumn).                 From<Product>().GetRecordCount();             Assert.IsTrue(records == 77);   Returning a Single object 
Product p = new Select().From<Product>().                Where(&quot;ProductID&quot;).IsEqualTo(1).ExecuteSingle<Product>();             Assert.IsNotNull(p); Returning a Single object using generated strongly typed variables 
Product p = new Select().From<Product>().                Where(Product.Columns.ProductID).IsEqualTo(1).ExecuteSingle<Product>();             Assert.IsNotNull(p);  Returning all columns 
int records = new Select().From(&quot;Products&quot;).GetRecordCount();             Assert.IsTrue(records == 77); Simple Where 
int records = new Select().From(&quot;Products&quot;).                 Where(&quot;categoryID&quot;).IsEqualTo(5).GetRecordCount();             Assert.AreEqual(7, records);  Simple Where with And (as Collection) 
ProductCollection products =                 DB.Select().From(&quot;Products&quot;)                     .Where(&quot;categoryID&quot;).IsEqualTo(5)                     .And(&quot;productid&quot;).IsGreaterThan(50)                     .ExecuteAsCollection<ProductCollection>(); Simple Inner Join 
SubSonic.SqlQuery q = new Select(&quot;productid&quot;).From(OrderDetail.Schema)                 .InnerJoin(Product.Schema)                 .Where(&quot;CategoryID&quot;).IsEqualTo(5); Simple Join With Table Enum 
SubSonic.SqlQuery q = new Select().From(Tables.OrderDetail)                 .InnerJoin(Tables.Product)                 .Where(&quot;CategoryID&quot;).IsEqualTo(5); Multiple Joins As Collection 
CustomerCollection customersByCategory = new Select()                 .From(Customer.Schema)                 .InnerJoin(Order.Schema)                 .InnerJoin(OrderDetail.OrderIDColumn, Order.OrderIDColumn)                 .InnerJoin(Product.ProductIDColumn, OrderDetail.ProductIDColumn)                 .Where(&quot;CategoryID&quot;).IsEqualTo(5)                 .ExecuteAsCollection<CustomerCollection>(); Left Outer Join With Generics 
SubSonic.SqlQuery query = DB.Select(Aggregate.GroupBy(&quot;CompanyName&quot;))                 .From<Customer>()                 .LeftOuterJoin<Order>(); Left Outer Join With Schema 
SubSonic.SqlQuery query = DB.Select(Aggregate.GroupBy(&quot;CompanyName&quot;))                 .From(Customer.Schema)                 .LeftOuterJoin(Order.CustomerIDColumn, Customer.CustomerIDColumn); Left Outer Join With Magic Strings 
SubSonic.SqlQuery query = DB.Select(Aggregate.GroupBy(&quot;CompanyName&quot;))                 .From(&quot;Customers&quot;)                 .LeftOuterJoin(&quot;Orders&quot;); Simple Select With Collection Result 
ProductCollection p = Select.AllColumnsFrom<Product>()                 .ExecuteAsCollection<ProductCollection>(); Simple Select With LIKE 
ProductCollection p = DB.Select()                 .From(Product.Schema)                 .InnerJoin(Category.Schema)                 .Where(&quot;CategoryName&quot;).Like(&quot;c%&quot;)                 .ExecuteAsCollection<ProductCollection>(); Using Nested Where/And/Or 
ProductCollection products = Select.AllColumnsFrom<Product>()                 .WhereExpression(&quot;categoryID&quot;).IsEqualTo(5).And(&quot;productid&quot;).IsGreaterThan(10)                 .OrExpression(&quot;categoryID&quot;).IsEqualTo(2).And(&quot;productID&quot;).IsBetweenAnd(2, 5)                 .ExecuteAsCollection<ProductCollection>();              ProductCollection products = Select.AllColumnsFrom<Product>()                 .WhereExpression(&quot;categoryID&quot;).IsEqualTo(5).And(&quot;productid&quot;).IsGreaterThan(10)                 .Or(&quot;categoryID&quot;).IsEqualTo(2).AndExpression(&quot;productID&quot;).IsBetweenAnd(2, 5)                 .ExecuteAsCollection<ProductCollection>();   OR when the above is done manually (notice manual opening and closing of expressions):              ProductCollection products = Select.AllColumnsFrom<Product>()                 .OpenExpression().Where(&quot;categoryID&quot;).IsEqualTo(5).And(&quot;productid&quot;).IsGreaterThan(10).CloseExpression()                 .Or(&quot;categoryID&quot;).IsEqualTo(2).AndExpression(&quot;productID&quot;).IsBetweenAnd(2, 5)                 .ExecuteAsCollection<ProductCollection>(); Simple Paged Query 
SubSonic.SqlQuery q = Select.AllColumnsFrom<Product>().                Paged(1, 20).Where(&quot;productid&quot;).IsLessThan(100); Paged Query With Join 
SubSonic.SqlQuery q = new Select(&quot;ProductId&quot;, &quot;ProductName&quot;, &quot;CategoryName&quot;).                 From(&quot;Products&quot;).InnerJoin(Category.Schema).Paged(1, 20); Paged View              SubSonic.SqlQuery q = new Select().From(Invoice.Schema).Paged(1, 20); Simple IN Query 
int records = new Select().From(Product.Schema)                 .Where(&quot;productid&quot;).In(1, 2, 3, 4, 5)                 .GetRecordCount();             Assert.IsTrue(records == 5); Using IN With Nested Select              int records = Select.AllColumnsFrom
()                 .Where(&quot;productid&quot;)                 .In(                 new Select(&quot;productid&quot;).From(Product.Schema)                     .Where(&quot;categoryid&quot;).IsEqualTo(5)                 )                 .GetRecordCount();  Using Multiple INs 
SubSonic.SqlQuery query = new Select()                 .From(Product.Schema)                 .Where(Product.CategoryIDColumn).In(2)                 .And(Product.SupplierIDColumn).In(3);</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Setting up SubSonic 2.x]]></title>
    <link href="http://subsonic.github.io/2010/01/17/setting_up_subsonic_2x/"/>
    <updated>2010-01-17T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/01/17/setting_up_subsonic_2x</id>
    <content type="html"><![CDATA[<h1>Setting up SubSonic 2.x</h1>

<h2>Screencast== To make things simple, we put together a quick screencast for you:  <swf height="480" width="640">/docs/media/intro.swf</swf>  ==Walkthrough</h2>

<p>Open up the App/Web.config file - we need to do a little surgery. First, declare a config section for SubSonic, right under the <configuration></configuration><compilation" ="Other" Notes=""></compilation">
.</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Help]]></title>
    <link href="http://subsonic.github.io/2010/01/12/help/"/>
    <updated>2010-01-12T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2010/01/12/help</id>
    <content type="html"><![CDATA[<h1>Help</h1>

<p>This here docs site is a Wiki and works based on help by 
. We&#39;d love your input and feedback - here&#39;s some resources for you:  </p>

<h2>Note== This is a wiki, which is intended to be a resource of information, not a place to ask questions. If you have a question please head over to StackOverflow (click the "Help" link above).  ==Style Guide</h2>

<p>Please have a read of our 
, 
.  </p>

<h2>Linking== Linking your document will help it be discovered - please make sure to read the help doc and link away!  ==Categories== Categories will help us find your page. One category is super-important: New Page. When you create a page for us, please mark it as a New Page (using [[Category:New Page]]) so we can find it!  ==Thank you!</h2>

<p>Honestly and truly - thank you for your interest in this :)</p>
]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Conventions]]></title>
    <link href="http://subsonic.github.io/2009/12/16/conventions/"/>
    <updated>2009-12-16T00:00:00-08:00</updated>
    <id>http://subsonic.github.io/2009/12/16/conventions</id>
    <content type="html"><![CDATA[<h1>Conventions</h1>

<h2>Philosophy== You hear it a lot: Convention Over Configuration. This is the Ruby On Rails mantra and had a lot of merit. At its core it means that what you do (especially if you've done it a lot) should carry a lot more weight than having to configure (and reconfigure) things over and over.  ==General Conventions==  *Column names should never contain reserved words (system, string, int, etc) *Column names should not be the same as table names  ===Primary Keys=== If you want to use SubSonic to access your table, you need to have a Primary Key defined for your table. This is good practice in every case and we need it to do certain things with your table. If you don't have a Primary Key defined, your class won't be generated.  If you don't believe us, or if you think this is a silly convention - SubSonic isn't for you.  ===Lookup Tables=</h2>

<p>For lookup tables, the key should be the first column and the &quot;
 the second column. Many of our lookup functions depend on this. Column names such as &quot;ShortDescription&quot; will have labels such as &quot;Short Description&quot; in scaffold.  </p>

<h2>ActiveRecord Specific Conventions==  ===Built-in Auditing=== Every table can have some auditing ability built in, but this is not required.  These fields are:  *CreatedOn (datetime) *CreatedBy (nvarchar(50)) *ModifiedOn (datetime) *ModifiedBy (nvarchar(50))  ===Logical Deletes=== If you want to use logical deletes, you can by adding a field called "Deleted" or "IsDeleted"  ==SimpleRepository Specific Conventions==  * Generated table names will be plural  ===Primary Keys=== If you call a column ID or Key or [ClassName]ID  no matter its type  that will be your Primary Key. If you have other things in mind you can use a primary key attribute [SubSonicPrimaryKey] contained in the SubSonic.SqlGeneration.Schema namespace and well use that column.  ===String length=== There are two ways to tell SubSonic how to handle this  both using attributes. The first is [SubSonicStringLength(int] and the second is [SubSonicLongString] which sets to nvarchar(MAX) or LONGTEXT  depending on your provider.  ===Nullability=== The default is not null, but you can change this by making your propery a nullable type.  ===Numeric Precision=== The default is a Precision of 10 and a scale of 2 but you can change that with the [SubSonicNumericPrecision(int] attribute.      ===Ignoring a Property=</h2>

<p>You can ignore generation of a property by using [SubSonicIgnore] attribute.</p>
]]></content>
  </entry>
  
  
</feed>
