PLINQO - What LINQ to SQL Was Supposed To Be

by bigcarlito Thursday, March 11, 2010

Lately I've been spending some time trying to optimize the amount of time it takes to develop web applications.  I've realized that it just takes way too much time to do tasks that are common for pretty much every project I work on.  Number one on the list has got to be creating a good data layer for an app.  My last big project used LINQ to SQL on the backend and I was very happy with how that turned out.  The only big complaint I had was that my changes would always get overwritten whenever I refreshed the DBML.  I also had some smaller issues with the lack of support for many-to-many relationships.  

Well here we are, almost a year and a half after Microsoft acknowledged that they were done with LINQ to SQL in favor of Entity Framework and I am still not seeing anything tangible that EF provides to me over LINQ to SQL.  I can see what it brings to enterprise developers with big clunky apps supported by many developers, but I need something lightweight that just works, and that's what LINQ to SQL is for me.  Now just imagine what L2S could be if MS had invested that time in updating the LINQ to SQL tools and language.

Well my friends, I'm happy to say that we don't have to imagine, because we have PLINQO!  PLINQO is an amazing set of templates for the CodeSmith code generation tool.   PLINQO examines your existing database and not only auto-generates an excellent strongly typed LINQ to SQL-based data layer in seconds, but actually enhances LINQ to SQL with some amazing extension methods.  Here's just a partial list of what I love about PLINQO:  

   - Automatic support for many-to-many relationship (very cool!)

   - Auto-generates extension methods for filtering by keys and indexes, including non-equality operators!

   - Caching extension methods for dead simple caching of queries

   - Generates a nice business layer with a very slick business rules engine

   - Future queries feature for batching multiple queries to a single database call

   - Want to change or enhance the generated code?  Just edit the templates to your heart's content!

   - And I saved the best for last: your DBML changes are NOT overwritten when you regenerate! 

I have to say, I'm amazed at what can be done with CodeSmith.  I'm going to have to spend some time looking into what else I can generate with this great tool.  I should have a lot more time to do that now that I've found PLINQO :-) .  

I was extremely disappointed when I heard that Microsoft was basically abandoning LINQ to SQL.  I felt forced to move on to other solutions like nHibernate.  Now I see that LINQ to SQL is alive and being supported and improved upon as well or possibly better than Microsoft itself would've done.  Thank you PLINQO!  

P.S.  If you are a fan of LINQ to SQL or even just a fan of working smarter not harder, then you at least owe it to yourself to commit 4 minutes and 8 seconds to watch the intro video on PLINQO.com.

  

Share/Save/Bookmark     kick it on DotNetKicks.com

Using Dynamic Data Controls In Your Existing Project

by bigcarlito Tuesday, October 07, 2008

Just about every site I've ever created has needed some screens to manage the data in certain tables - whether it's users, products, or in my most recent case forums.  I always overlook the time it takes to make a basic CRUD (CReate-Update-Delete) screen. 

There really is a lot of work that goes into these types of screens: Get the data, hook the data up to a grid, format the grid and the fields in the grid, create a details view, format the details view and the detail fields, hook the details view up to the grid, enable editing of the fields, validate the inputs on save, save or insert the data, refresh the grid after saving, and on and on it goes.  PHEW! 

"Uh, excuse me Mr. Project Manager, how long did I estimate for this task again?" :-) 

Dynamic Data To The Rescue

After installing Visual Studio 2008 SP1, you may have noticed a new web application project called Dynamic Data Web Application.  A Dynamic Data web application provides a framework for quickly and easily creating CRUD screens for any tables in your database.

However, an entire web application dedicated to managing the data in a database is not very practical.  In a typical software project, whatever CRUD screens you need are usually just a small piece of the entire application.

The good news is that Dynamic Data is fairly easily integrated into your existing projects as well.  Props to Scott Hanselman for explaining clearly how to do this

So here's a summary of exactly how I went about adding screens for managing the Forums table in my existing application:

Step 1: Add Dynamic Data To Your Project

There are a few specific things you'll need to do to add Dynamic Data to your Web Forms or MVC project:

I. Add a reference to System.Web.DynamicData 

II. Add dynamic data controls to the <controls> element of your web.config

<pages>
    <controls>
        <add tagPrefix="asp" namespace="System.Web.DynamicData" 
assembly="System.Web.DynamicData, Version=3.5.0.0, 
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>  
    </controls>
 

III.  Register your model in Global.asax

protected void Application_Start()
{
   MetaModel model = new MetaModel(); 
   model.RegisterContext(typeof(SocialDataContext), 
new ContextConfiguration() { ScaffoldAllTables = false });
   RegisterRoutes(RouteTable.Routes);
}

IV.  Add the DynamicData folder and contents to your project

As suggested by Scott H., the best way to do this is to go create a brand new Dynamic Data Web Application project off in another directory.  Be sure to name the new project the exact same name as your current project so namespaces will all match up.  Once created, copy the DynamicData folder and all it's contents over to your project directory and include the entire thing in your project.

 

Step 2: Create A Web Form and add a DynamicDataManager

Pretty simple, create your web form and and add the DynamicDataManager control to it:

<asp:DynamicDataManager ID="DynamicDataManager1" runat="server" />  

Step 3: Add A GridView

Next step is to add a grid that will contain the table data. The only really interesting part here is the columns of the gridview - they are controls of type DynamicControl. These smart controls look at the type of data they are given and automatically determine the best way to display it:

<!-- The Data -->
<asp:LinqDataSource ID="DataSourceItems" runat="server" 
ContextTypeName="Social.Models.SocialDataContext" EnableDelete="True" 
EnableInsert="True" EnableUpdate="True" TableName="Forums" 
OrderBy="DisplayOrder, ForumName">
</asp:LinqDataSource>
<!-- The Grid -->
<asp:GridView ID="gvItems" runat="server" AllowPaging="True" AllowSorting="True" 
AutoGenerateColumns="False" DataSourceID="DataSourceItems" 
onselectedindexchanged="gvItems_SelectedIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" HeaderStyle-Width="60" />
<asp:TemplateField HeaderText="Forum" SortExpression="ForumName">
<ItemTemplate>
<asp:DynamicControl ID="DynamicControl1" runat="server" DataField="ForumName" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Category" SortExpression="ForumCategory.ForumCategory1">
<ItemTemplate>
<asp:DynamicControl ID="DynamicControl2" runat="server" DataField="ForumCategory" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Sort" SortExpression="DisplayOrder">
<ItemTemplate>
<asp:DynamicControl ID="DynamicControl3" runat="server" DataField="DisplayOrder" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<!-- An 'Add New' Button -->
<div class="addrow">
<asp:LinkButton ID="btnInsert" runat="server" onclick="btnInsert_Click">Add New
</asp:LinkButton>
</div>

Step 4: Add The Details View

Next up we'll add the details view where the user will be able to update any editable properties of the selected item or add a new item.  Again the interesting part (and the part you'll change when you make your own page) are the DetailsView columns.

The DynamicField controls peek at the datatype of the field they are bound to and provide the appropriate input control for that datatype.  Not only that, but validation is built in as well!  Pretty neat, eh?

<!-- Details -->
<asp:Panel ID="PanelDetails" runat="server" Visible="false">
<!-- Input Fields -->
<asp:DetailsView ID="dvItem" runat="server" 
AutoGenerateRows="False" DataKeyNames="ForumID" DataSourceID="DataSourceDetails" 
AutoGenerateDeleteButton="True" AutoGenerateEditButton="True" 
AutoGenerateInsertButton="True" onitemdeleted="dvItem_ItemDeleted" 
onitemupdated="dvItem_ItemUpdated" oniteminserted="dvItem_ItemInserted"> 
<Fields>
<asp:DynamicField DataField="ForumID" HeaderStyle-Width="150" HeaderText="Forum ID:" />
<asp:DynamicField DataField="ForumName" HeaderText="Forum Name:" />
<asp:DynamicField DataField="ForumDesc" HeaderText="Description:" />
<asp:DynamicField DataField="DisplayOrder" HeaderText="Sort:" />
<asp:DynamicField DataField="ForumCategory" HeaderText="Category:" />
<asp:DynamicField DataField="IsPrivate" HeaderText="Private:" />
<asp:DynamicField DataField="ParentForum" HeaderText="Parent:" />
</Fields>
</asp:DetailsView>
<!-- Details DataSource -->
<asp:LinqDataSource ID="DataSourceDetails" runat="server" 
ContextTypeName="Social.Models.SocialDataContext" EnableDelete="True" 
EnableInsert="True" EnableUpdate="True" TableName="Forums" 
Where="ForumID == @ForumID">
<WhereParameters>
<asp:ControlParameter ControlID="gvItems" DefaultValue="-1" Name="ForumID" 
PropertyName="SelectedValue" Type="Int32" />
</WhereParameters>
</asp:LinqDataSource>
</asp:Panel> 

In software development, it often is all the little things that take up the most time.  The old saying 'the last 20% is 80% of the work' certainly is true in my experience.  Dynamic Data is a huge timesaver in that regard, it handles all the little details of a common but typically painstaking task.

Step 5: Handle A Few Events

Finally, in the code behind, we'll handle a few of the events to make the flow of work a little smoother.  Notice how little code is required to make this fully featured CRUD screen:

    protected void Page_Load(object sender, EventArgs e)
    {
      DynamicDataManager1.RegisterControl(gvItems);
      DynamicDataManager1.RegisterControl(dvItem);
    }
    protected void gvItems_SelectedIndexChanged(object sender, EventArgs e)
    {
      PanelDetails.Visible = true;
    }
    protected void btnInsert_Click(object sender, EventArgs e)
    {
      dvItem.ChangeMode(DetailsViewMode.Insert);
      PanelDetails.Visible = true;
    }
    protected void dvItem_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
    {
      RefreshGrid();
    }
    protected void dvItem_ItemDeleted(object sender, DetailsViewDeletedEventArgs e)
    {
      RefreshGrid();
    }
    protected void dvItem_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
    {
      RefreshGrid();
    }
    private void RefreshGrid()
    {
      gvItems.DataBind();
      gvItems.SelectedIndex = -1;
    }

So How Do I Use This?

For anyone wanting to use this, here's what you need to change to suit your situation:

  1.  Edit the grid's datasource to pull data from your table in your DataContext
  2.  Update the grid's columns - most importantly the DataField properties - to match the fieldnames (or in this case LINQ properties) from your table
  3.  Update the details datasource pull the specific record from your table based on the key field from grid
  4.  Update the details view to include all the columns that cannot be null or that you want to be editable by the user

That's it!  Pretty much everything else is handeled through the magic of Dynamic Data!

A Dynamic Data app also comes with a lot of scaffolding for mapping URLs to tables and dynamically generating entire CRUD pages.  The purpose of this post was simply to show how to use the Dynamic Data controls in your existing projects with minimal changes to how the rest of your project does things. Hope it was helpful!
Share/Save/Bookmark     kick it on DotNetKicks.com

URL Rewriting Extension For BlogEngine

by bigcarlito Tuesday, August 05, 2008

In my latest project I decided to incorporate BlogEngine.Net for managing the content.  While it certainly does have some things I don't like, all in all it's an excellent basic content system.  I love the control over the HTML that you get with the theme system, the flexibility provided by extensions and widgets, and the integration with Windows Live Writer - truly a job well done by Mads and the BE.NET team!

During A Redesign, Think About Search Visitors

So I have an existing site More...

Share/Save/Bookmark     kick it on DotNetKicks.com

Using jQuery To Call ASP.NET Page Methods and Web Services

by bigcarlito Wednesday, July 16, 2008

I'm a HUGE fan of jQuery.  In fact in my latest project, I've removed the ScriptManager from my ASP.NET pages entirely.  Originally I was including both jQuery and the ScriptManager on my pages because I just couldn't live without the ease and simplicity of calling page methods with ASP.NET AJAX. 

Well, with a little help from Dave Ward and Rick Strahl, I realized that calling ASP.NET page methods (and web services) from jQuery is really pretty simple. More...

Share/Save/Bookmark     kick it on DotNetKicks.com

Five Common ASP.NET SEO Mistakes

by bigcarlito Tuesday, July 08, 2008

Search Engine RobotSo you've finally finished your next masterpiece of a website.  Everything is tested and working great.  The user interface is immaculate and the design is truly something to behold.  Time to push it live and start rolling in the money, right?  Well, there is one more user demographic that you still need to satisfy - the search engines!  Unless, of course, you don't *need* any of that free targeted search traffic??

One of the strengths of ASP.NET development with Visual Studio is the relative ease in which you can create a functional dynamic site.  At the same time, one of it's weaknesses is the relative ease in which you can create a functional dynamic site that is confusing, if not completely unusable, by a search engine robot.

Here's a checklist of five common mistakes that ASP.NET and the Viewstate/Postback model of development make it far too easy for unsuspecting developers to make: More...

Share/Save/Bookmark     kick it on DotNetKicks.com

Deploying ASP.NET Applications With Dispatch

by bigcarlito Wednesday, March 05, 2008

As a web developer with many sites, it quickly became a major time consuming problem to keep them all updated with the latest code.  Visual Studio has never had a good solution for deploying the necessary files (and only the necessary files) directly to a web server. 

Sure, they provide a feeble attempt at an FTP synchronization tool, but this tool has never really proved to be anything more than an integrated FTP client, leaving the developer to manually upload the files that need to be uploaded, updating configuration files for the remote server, and most importantly, ensuring that nothing gets overwritten that shouldn't be.  More...

Share/Save/Bookmark     kick it on DotNetKicks.com