Mike Borozdin's Blog

A blog about programming, web and IT in general

Understanding Attaching/Detaching Objects in LINQ to SQL and in the Entity Framework

LINQ to SQL and the Entity Framework are very powerful tools, however as in many other useful tools there are some things you should be aware of when working with them. One of those things is object attaching and detaching. Let’s have a concrete example.

As you already know, you can retrieve an object from the database, update or remove it and all the necessary changes will be submitted to the database.

But what if you don’t want to perform additional SELECT query? Instead, you want just to perform one necessary query, either to update an object or remove it

Well, a quite logical idea is to create an object, set an appropriate ID attribute and then update/delete it:

NorthwindDataContext db = new NorthwindDataContext();
 
Product product = new Product { ProductID = 1 };
 
db.Products.DeleteOnSubmit(product);
 
db.SubmitChanges();

Okay, but it won’t work. The code will gets compiled, but when executed it will throw an exception stating: “Cannot remove an entity that has not been attached.” Well, in fact, it’s quite obvious, because the object context is simply unaware of that object, so let it know about the object. We just need to attach the object to the object context:

NorthwindDataContext db = new NorthwindDataContext();
 
Product product = new Product { ProductID = 1 };
db.Products.Attach(product); //that necessary line
 
db.Products.DeleteOnSubmit(product);
 
db.SubmitChanges();

So, if you compile it now, you will get no exceptions and the necessary product will be removed from the database. You can use the same technique when you need to update an object without having to retrieve it from the database and the same thing applies to the Entity Framework, although the code is slightly different:

NorthwindEntities db = new NorthwindEntities();

Product product = new Product { ProductID = 10 };
product.EntityKey = new EntityKey("NorthwindEntities.Products", "ProductID", 10);
db.Attach(product);

db.DeleteObject(product);

db.SaveChanges();

Posted by Mike Borozdin on Thursday, January 15, 2009 4:12 AM GMT
Shout it Kick it!  
Permalink | Comments (3) | Post RSSRSS comment feed

The List of the LINQ to SQL and Entity Framework Providers

If you are using Microsoft SQL Server you don’t experience any problems, SQL Server are supported by both LINQ to SQL and the Entity Framework. Frankly speaking, it couldn’t be otherwise, since they all are made by Microsoft.

However, if you are using a non-Microsoft database engine, it’s certainly worth knowing if you can use LINQ to SQL or the Entity Framework with it. Moreover, it’s always better if there is native support.

  LINQ to SQL (native) LINQ to SQL (3rd party) Entity Framework (native) Entity Framework
(3rd party)
SQL Server Yes who cares? Yes who cares?
SQl Server CE Yes who cares? Yes who cares
Oracle No DBLinq
LINQ to Oracle
LightSpeed
dotConnect
Yes dotConnect
EFOracle
DB2 No ? Yes ?
MySQL No DBLinq
LightSpeed
Planned dotConnect
PostgreSQL No Npgsql
DBLinq

LightSpeed
dotConnect
No Npgsql
dotConnect

According to the table, the Entity Framework is natively supported by a greater number of databases than plain LINQ to SQL. Anyway, if you cannot find a native provider, you can always find a 3rd party one, but you must remember that some of them are not free and/or may lack some features.

Feel free to correct this table, if it contains a mistake and comment on individual providers. It’s reasonable to keep this list comprehensive. Although I wish every major database would have native support of both technologies.


Posted by Mike Borozdin on Tuesday, January 06, 2009 1:10 PM GMT
Shout it Kick it!  
Permalink | Comments (7) | Post RSSRSS comment feed

Creating a Simple Ad Rotation User Control with LINQ to XML

Download files

Although there is a built-in control for advertisement rotation in ASP.NET, it is capable of showing image ads only. However, in the real life you often have to deal with the ads that require some JavaScript code, for instance, you want to put there AdSense code or want to use Flash banners instead of images. Thus, if you want to rotate complex ads, you have to develop your own control.

In this particular tutorial I'll show you how to create a very simple, but rather functional user control that will randomly show an ad from an XML file of the following format:

<Advertisements>
    <Ad>
        <Html>
            <![CDATA[
                Some HTML code
            ]]>
        </Html>
    </Ad>
    
    <Ad>
        <Html>
            <![CDATA[
                Some other HTML code
            ]]>
        </Html>
    </Ad>
</Advertisements>

 

Well, as you can see, it's very very simple, there is even no NavigateUrl element, but we don't even need, because we can always put a link into the HTML element, besides usually we use something similar to AdSense, so there is no need defining the URL.

The control will accept have only one attribute - AdvertisementFile - which points to an XML file with ads. So, to ad a control, you just have to place a similar code:

<uc1:HtmlAdRotator runat="server" AdvertisementFile="~/App_Data/ads.xml" />

 

Let's start creating it. We should add a new user control to our web site, then put a <div> that will hold the content of advertisements.

<div id="adContent" runat="server"></div>

 

In the code-behind we define the only attribute the user control has, please note that we use a neat feature of C# 3.0 that simplifies creation of properties. In the Page_Load() method we extract the data from the specified XML file and pick-up a random ad from there. We use LINQ to XML for XML file parsing.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;

public partial class HtmlAdRotator : System.Web.UI.UserControl
{
    public string AdvertisementFile { get; set; }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        XDocument xAds = XDocument.Load(Server.MapPath(AdvertisementFile));

        var ads = from a in xAds.Descendants("Ad")
                  select (string)a.Element("Html");

        Random rand = new Random();
        var ad = ads.ElementAt(rand.Next(ads.Count()));
        adContent.InnerHtml = ad;
    }
}

So, with ASP.NET you can easily build your own control suits your needs in a few minutes, while LINQ to XML helps you to extract the data in a very elegant way.

Download files


Tags: ,
Posted by Mike Borozdin on Saturday, August 30, 2008 2:43 PM GMT
Shout it Kick it!  
Permalink | Comments (3) | Post RSSRSS comment feed

Is PHPLinq As Cool As Real LINQ?

I read about the PHP Implementation of LINQ called PHPLinq. Frankly, I was sceptical about it. Finally, I gave it a try. I still remain sceptical...


Let’s me explain why. Take a look at this fairly simple example, where we extract all the numbers greater than 5:

<?php

set_include_path(get_include_path() . PATH_SEPARATOR . '../PhpLinq/Classes/');
require_once('PHPLinq/LinqToObjects.php');

$numbers = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

$result = from('$number')->in($numbers)
            ->where('$number => $number > 5')
            ->select('$number');

print_r($result);           

?>

If you familiar with LINQ, then you may say: "Wow, that’s cool! Just like in .NET". Yes, the syntax is quite familiar. But if you look closer, you will notice that the query expressions are encloced in single quotes, i.e. they are just string. That makes a significant difference between PHPLinq and real LINQ. Do you remember what LINQ stands for? It stands for Language Intergrated Query. Unfortunately, PHPLinq isn’t a language integrated query, since it’s not supported by the language natively and we have to use strings for writting queries.

When we write real LINQ queries in Visual Studio we’ve got syntax highlighting, we’ve got IntelliSence and that is more important we can track errors at the compilation stage. PHPLinq lacks all these things. Ok, PHP is an interpreted language, so there’s no compilation stage; however there are smart IDEs that track errors while we’re writing code.


I want to illistrate this, let’s make a deliberate error, we’ll change $number to $number1 in the from clause. If you run the script you’ll get a notice, in case notices are enabled and nothing more.But if you are writing this in C#, it won’t even get compiled.


In the real world LINQ is used mostly as a SQL replace, we don’t have to write the queries in strings anymore and catch the exceptions when running an application. But unfortunately we cannot do the same with PHPLinq, it still forces us to put the queries into strings.


Well, I think I was sceptical enough about it, but still PHPLinq has some cool features, just check this example taken from the PHPLinq official web site:

<?php
/**
 * PHPLinq
 *
 * Copyright (c) 2008 PHPLinq
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category   PHPLinq
 * @package    PHPLinq
 * @copyright  Copyright (c) 2008 PHPLinq (http://www.codeplex.com/PHPLinq)
 * @license    http://www.gnu.org/licenses/lgpl.txt    LGPL
 * @version    0.3.0, 2008-06-23
 */

/** Error reporting */
error_reporting(E_ALL);

/** Include path **/
set_include_path(get_include_path() . PATH_SEPARATOR . '../Classes/');

/** PHPLinq_LinqToObjects */
include 'PHPLinq/LinqToObjects.php';

// Custom class
class Employee {
    public $Name;
    public $Email;
 
    public function __construct($name, $email) {
        $this->Name     = $name;
        $this->Email     = $email;
    }
}

// Create data source
$rssFeed = simplexml_load_string(file_get_contents('http://blog.maartenballiauw.be/syndication.axd'));
$result = from('$item')->in($rssFeed->xpath('//channel/item'))
            ->orderByDescending('$item => strtotime((string)$item->pubDate)')
            ->take(2)
            ->select('new {
                            "PostTitle" => (string)$item->title,
                            "PostAuthor" => (string)$item->author,
                            "MetaData" => new {
                                                "Url" => (string)$item->link,
                                                "Guid" => (string)$item->guid,
                                                "PostDate" => strtotime((string)$item->pubDate)
                                          }
                      }');
               
print_r($result);


Tags: ,
Posted by Mike Borozdin on Friday, July 04, 2008 2:45 PM GMT
Shout it Kick it!  
Permalink | Comments (9) | Post RSSRSS comment feed

LINQ To MySQL

LINQ to SQL is a great tool that saves a lot of time. However it has one disadvantage – it supports only SQL Server. Anyway it’s possible to write your own LINQ provider. Sure, there is one for MySQL. It is called DbLinq, in fact in supports many databases:

  • MySQL
  • Oracle
  • PostreSql
  • Ingress
  • SqlLite
It’s not finished yet, however you can still try to use it. I’m going to explain how to use it in this article; we’ll go through 3 steps:
  1. Installation
  2. Using DbLinq in a console application
  3. Using DbLinq in a ASP.NET application

Installation

  1. Go here and download the ZIP archieve
  2. Unpack the archive
  3. Open the Visual Studio solution - DbLinq
  4. Build the solution

Using DbLinq in a console application

Ok, let’s try it in action, we are going to create a console application that will retrieve, insert, update and delete records from the database.

First, we need to generate the data context and the table classes. Unfortunately you cannot do this in Visual Studio, but there is a command line utility called DbMetal and its visual analogue – Visual Metal that is written in WPF, by the way.


Go to the \dblinq2007\DbMetal\ folder, there are several BAT files, open in your favourite text editor run_myMetal.bat, since we are dealing with MySQL, and change the necessary parameters, save and run it. You must have got a generated CS file, copy it to your console application project.
Then, it’s time to add the references, you should add the following:

  • System.Data.Linq
  • DbLinq.dll (located in \dblinq2007\DbLinq.MySql\bin\release\)
  • DbLinq.MySql.dll (located in \dblinq2007\DbLinq.MySql\bin\release\)
  • MySql.Data.dll (located in \dblinq2007\lib\)

Since the table is called Products, I want the class that represents a stored entity to be called Product, not Products, as it was called by DbMetal. So, I change the generated code.


Compile the project to check if there are no errors. If you get any error, check if there are all the necessary references.


Let’s write some code; basically we want just to display the data:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient; //Don't forget to add this line

namespace MySqlLinqTest
{
    class Program
    {
        static void Main(string[] args)
        {
            LinqTest db = new LinqTest(new MySqlConnection("Database=<your database>;Data Source=localhost;User Id=<user>;Password=<password>"));

            var products = from p in db.Products
                           where p.Category == "Sport cars"
                           select p;

            foreach (var product in products)
            {
                Console.WriteLine(product.Name);
            }
        }
    }
}

That works. What about inserting a new record? No problems!

db.Products.InsertOnSubmit(new Product { Name = "Some car", Category = "Some category" });
db.SubmitChanges();

var products = from p in db.Products
               orderby p.Name
               select p; 

foreach (var product in products)
{
    Console.WriteLine(product.Name);
}

Ok, let’s remove the newly added record:

Product someCar = (from p in db.Products
                      where p.Name == "Some car"
                      select p).First();

db.Products.DeleteOnSubmit(someCar);
db.SubmitChanges();

Let’s update something:

Product bentley = (from p in db.Products
                   where p.Name == "Bentley"
                   select p).First();

bentley.Name = "Bentley Continental";
db.SubmitChanges();

Using DbLinq in an ASP.NET application

It was funny enough, but the console applications are not very useful when dealing with the database, let’s write something that is closer to a real world – an ASP.NET application.


Create a C# web site; copy the generated file we used in the previous example.


Don’t forget to add the necessary references.


We are going to add a GridView and bind the data retrieved from the database.

Default.aspx

<asp:GridView ID="gridProducts" runat="server">
</asp:GridView>

 

Default.aspx.cs 

protected void Page_Load(object sender, EventArgs e)
{
    LinqTest db = new LinqTest(new MySqlConnection("Database=<your database>;Data Source=localhost;User Id=<user>;Password=<password>"));

    gridProducts.DataSource = from p in db.Products
                              orderby p.Name
                              select p;
    gridProducts.DataBind();
}

It works.

What about LinqDataSource, can we use it with DbLinq? Yes, we can, but it’s a bit tricky. If we add a LinqDataSource, we’ll get an error saying that there’s no parametless constructor in our DataContext. That is a thing that hopefully will be fixed in the new versions, but now we have to write a wrapper around a generated DataContext.

App_Code/Products.cs

public class MyDataContext
{
    private LinqTest _db;

    public MyDataContext()
    {
        _db = new LinqTest(new MySqlConnection("Database=<your database>;Data Source=localhost;User Id=<user>;Password=<password>"));
    }

    public Table<Product> Products { get { return _db.GetTable<Product>(); } }
}

Then, we can use LinqDataSource as usual:


<asp:LinqDataSource ID="dsProducts" runat="server" ContextTypeName="MysqlLinqTest.MyDataContext"
    TableName="Products">
</asp:LinqDataSource>

<asp:GridView ID="gridProducts" runat="server" DataSourceID="dsProducts"> 
</asp:GridView>

Conclusion

As you see you can use LINQ to work with MySQL, unfortunately sometimes it’s not very convenient and we have to wait for the new versions or wait for a LINQ to MySQL provider from MySQL.
 


Tags:
Posted by Mike Borozdin on Thursday, June 26, 2008 8:30 AM GMT
Shout it Kick it!  
Permalink | Comments (9) | Post RSSRSS comment feed

A Practical Example Of Using The New Features Of ASP.NET 3.5

This tutorial doesn’t cover the theoretical basics of the new features and controls, instead it concentrates on the practical example of using the new features. This tutorial covers the following features:

  • LINQ (Language Integrated Query) for the data manipulations
  • ListView control for presenting the data
  • LinqDataSource for binding data
  • DataPager for pagination
  • ASP.NET AJAX for getting rid of the unncecesassary page reloads

Requirements:

  • Visual Studio 2008
  • SQL Server

Project

Our project is quite simply, it's just a guestbook, but it's good for demonstrating the cool features of ASP.NET 3.5 and .NET 3.5 in action.




 

So, just open Visual Studio and create a new C# website.

Database design
We need to create a database when the comments will be stored. We’ll just create a database with a single table that will keep the comments posted by the authors. We can create it in Server Explorer without leaving Visual Studio.

 



Don’t forget to set the Id field as an identity.
Let’s populate the database as well, so that we’ll have some data to display, just execute these queries:

INSERT INTO Comments
(Author, Text)
VALUES('John', 'ASP.NET 3.5 rocks!');

INSERT INTO Comments
(Author, Text)
VALUES('Mary', 'ASP.NET 3.5 is so cool!');
 

LINQ

Then, we need to create a LINQ To SQL class that will be using for the data manipulations (retrieving and inserting). We open Website->Add New Item and choose LINQ To SQL Classes

 




Then we open Server Explorer and drag and drop our table on the workspace.
 


Now we just save this file and go futher, we can view the generated code though located in App_Code\Comments.dbml\Comments.designer.cs

LinqDataSource

Ok, it’s a time for create your webform that will hold all the content. Actually, it is already created by Visual Studio, we just have to add some content there.
We are going to start with a data source, open Toolbox, expand the data section and find LinqDataSource there. 

 



Drag it to the webform.  You will get the following code:


<asp:LinqDataSource ID="LinqDataSource1" runat="server">
</asp:LinqDataSource>


Give it a more appopriate name, something like dsComments. Now switch to the Design view, click on the LinqDataSource we’ve just added and select Configure Data Source.

 



Choose the only avaliable data context object and click Next.


 
Then leave everything by default by click on the Order By button. And choose Id and the Descending order.


 
Click Ok and finish, switch to the Source view and look at the code we get:


<asp:LinqDataSource ID="dsComments" runat="server"
    ContextTypeName="CommentsDataContext" EnableInsert="True" OrderBy="Id desc"
    TableName="Comments">
</asp:LinqDataSource>

 

Pretty simple, I would say.

ListView

It’s time to add the ListView control. It’s a new data bound control that enables you to have a full control of the rendered HTML code. It’s also located in the Data section of Toolbox. Drag it and rename it to lvComments, also don’t forget to assign a data source to it. You must get the following code:


<asp:ListView ID="lvComments" runat="server" DataSourceID="dsComments">
</asp:ListView>


Then, we have to add the <LayoutTemplate> that will be the root template


<asp:ListView ID="lvComments" runat="server" DataSourceID="dsComments">
    <LayoutTemplate>
        <h1>ASP.NET Guestbook</h1>
        <div id="itemPlaceholder" runat="server"></div>
    </LayoutTemplate>
</asp:ListView>

 

Please, note the we have the div tag with id="itemPlaceholder" runat="server". They denote that ListView content will be placed in the place of that div, itemPlaceholder is the default ID of the content placeholder.

To display out data we should add the <ItemTemplate> element and place some content there


<ItemTemplate>
    <div>
        <b><%# Eval("Author") %></b> says<br />
        <%# Eval("Text") %>
    </div>
</ItemTemplate>


It’s simply and has nothing new if you worked with other data bound controls. Let’s add the separator element to separate the posts:


<ItemSeparatorTemplate>
    <hr />
</ItemSeparatorTemplate> 


Compile the website, you should you see a very simply webpage with just two comments by Mary and John that we added in the very beginning. It’s cool, but what about enabling users to post comments? It also can be done by using LinqDataSource and ListView.

First, add EnableInsert=”True” attribute to the LinqDataSource. Second, we need to add the insert item template to the ListView.


<InsertItemTemplate>
    Name:<br />
    <asp:TextBox ID="txtBox" runat="server" Text='<%# Bind("Author") %>' /><br />
    Text:<br />
    <asp:TextBox ID="txtText" runat="server" Text='<%# Bind("Text") %>'
        TextMode="MultiLine" /><br />
    <asp:Button runat="server" CommandName="Insert" Text="Post" /><br />
</InsertItemTemplate>     


 


Pay attetion at two things – data binding in the input controls and the CommandName attribute in the button. If you compile the website right now, you won’t see see the post form because you should define its position first, to do that add InsertItemPosition="FirstItem" to the ListView attributes, you can set it to LastItem however.

Now compile the project and try posting some comments. It’s working that is good.

DataPager

It’s time to add a pagination and see another new control in action. It is called DataPager. Add the following code to the LayoutTemlate of the ListView:


<asp:DataPager runat="server" PagedControlID="lvComments" PageSize="5">
    <Fields>
        <asp:NumericPagerField />
    </Fields>
</asp:DataPager> 

I suppose it’s pretty self-explanatory, PagedControlID defined the control we want to page, PageSize sets the number of entries per page. <asp:NumericPagerField /> says that we want to have the list of the page numbers. Compile it and try it in the browser.


I guess you noticed that it has an ugly postback in its URL. You can easily get rid of it by adding the QueryStringField attribute to the DataPager and of course by setting its value ;-).


<asp:DataPager runat="server" PagedControlID="lvComments" PageSize="5"
                    QueryStringField="page">

It looks much better now and you can send the link to the 10th page of your guestbook to a friend.

ASP.NET AJAX


At the final stage, let’s add some AJAX, so that the page doesn’t reload each time you post a comment. Visual Studio 2008 has a built-in ASP.NET AJAX library which is extremely easy in use.


Open Toolbox, expand AJAX Extensions and drop ScriptManager to the page. ScriptManager is a control that loads all the necessary JavaScript libraries needed for ASP.NET AJAX. If you forget to add ScriptManager, you’ll get an error.


So, we don’t want the whole page to be updated when posting a comment, we just want to update our ListView, so we are surrounding the ListView with UpdatePanel.


<asp:UpdatePanel runat="server">
    <ContentTemplate>
        <% List View code %>
    </ContentTemplate>
</asp:UpdatePanel>


Compile the website and post a comment, notice that the page doesn’t get reloaded this time.

Conclusion

There are a lot of cool features in ASP.NET that help you make your applications much faster than in ASP.NET 2.0. We have build a guestbook without writing a line of C# code. Of course this tutorial wasn't mean to cover all the features of ASP.NET 3.5, it doesn't cover the basics things, however you can find them on MSDN and on ww.asp.net.

Code

35NewFeatures.zip (5.80 kb)


Tags: ,
Posted by Mike Borozdin on Sunday, June 22, 2008 11:48 AM GMT
Shout it Kick it!  
Permalink | Comments (7) | Post RSSRSS comment feed