2009年7月8日水曜日

LINQ TO SQL on Mono 2.4

このエントリーをはてなブックマークに追加
そういや、試してなかったな、ということでやってみた。

的は Windows 7 RC1(VirtualBox 2.2.4 のゲスト OS)上の SQL Server 2008 Express Edition。

テーブルはいつものこれ。
CREATE TABLE dbo.Products(
  ProductID int PRIMARY KEY NOT NULL,
  ProductName varchar(25) NOT NULL,
  Price money NULL,
  ProductDescription nvarchar(128) NULL)
GO
試してみたコードはこれ。
using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;

namespace SqlServerExample
{
  [Table(Name="Products")]
  public class Product
  {
    [Column(Name="ProductID", IsPrimaryKey=true)]
    public int Id;

    [Column(Name="ProductName")]
    public string Name;

    [Column(Name="Price")]
    public decimal? Price;

    [Column(Name="ProductDescription")]
    public string Description;

    public override string ToString()
    {
      return "ID:" + Id + " NAME:" + Name + " PRICE:" + Price + " DESCRIPTION:" + Description;
    }
  }

  public class Program
  {
    public static void Main(string[] args)
    {
      string constr =
        "Data Source=192.168.1.x,49174;" +
        "Initial Catalog=TestData;" +
        "User ID=sta;" +
        "Password=passw0rd;" +
        "Trusted_Connection=False";

      DataContext db = new DataContext(constr);

      Table<Product> Products = db.GetTable<Product>();

      var results =
        from p in Products
        orderby p.Id
        select p;

      foreach (Product p in results)
      {
        Console.WriteLine(p);
      }
    }
  }
}
実行。

$ gmcs -r:System.Data.Linq.dll l2sql.cs
$ mono l2sql.exe

Unhandled Exception: System.NotImplementedException: The requested feature is not implemented.
at SqlServerExample.Program.Main (System.String[] args) [0x00000]

よし、未実装、撤収。

・・・と、残念な展開なんで、dblinq を試してみることにした。

ソースを svn checkout して

$ svn co http://dblinq2007.googlecode.com/svn/trunk/ dblinq2007-read-only

MonoDevelop で ソリューション DbLinq.sln を開いて、プロジェクト DbLinq、DbLinq.SqlServer をビルド。

試してみたコードはこれ。
using System;
using System.Data.Linq.Mapping;
using System.Data.SqlClient;
using System.Linq;

using DbLinq.Data.Linq;
using DbLinq.SqlServer;

namespace dblinqExample
{
  [Table(Name="Products")]
  public class Product
  {
    [Column(Name="ProductID", IsPrimaryKey=true)]
    public int Id;

    [Column(Name="ProductName")]
    public string Name;

    [Column(Name="Price")]
    public decimal? Price;

    [Column(Name="ProductDescription")]
    public string Description;

    public override string ToString()
    {
      return "ID:" + Id + " NAME:" + Name + " PRICE:" + Price + " DESCRIPTION:" + Description;
    }
  }

  public class Program
  {
    public static void Main(string[] args)
    {
      string constr =
        "Data Source=192.168.1.x,49174;" +
        "Initial Catalog=TestData;" +
        "User ID=sta;" +
        "Password=passw0rd;" +
        "Trusted_Connection=False";

        // 詳細
        //DbLinq.Data.Linq.DataContext db = new DbLinq.Data.Linq.DataContext(new SqlConnection(constr), new DbLinq.SqlServer.SqlServerVendor());

        DataContext db = new DataContext(new SqlConnection(constr), new SqlServerVendor());

        Table<Product> Products = db.GetTable<Product>();

        var results =
          from p in Products
          orderby p.Id
          select p;

        foreach (Product p in results)
        {
          Console.WriteLine(p);
        }
      }
    }
  }
実行(事前に DbLinq.dll、DbLinq.SqlServer.dll を環境変数 MONO_PATH に設定してるディレクトリにコピーした)。

$ gmcs -r:System.Data.dll,System.Data.Linq.dll,DbLinq.dll,DbLinq.SqlServer.dll l2sqlserver.cs
$ mono l2sqlserver.exe
ID:0 NAME:SQL Server PRICE: DESCRIPTION:SQLServer 2008 Express Edition
ID:1 NAME:Clamp PRICE:12.4800 DESCRIPTION:Workbench clamp
ID:50 NAME:Flat Head Screwdriver PRICE:3.1700 DESCRIPTION:Flat head
ID:75 NAME:Tire Bar PRICE: DESCRIPTION:Tool for changing tires.
ID:3000 NAME:3mm Bracket PRICE:0.5200 DESCRIPTION:

おおお、うまくいっちゃった。

少し体裁を整えて、より LINQ TO SQL っぽく、
using System;
using System.Data.Linq.Mapping;
using System.Data.SqlClient;
using System.Linq;

using DbLinq.Data.Linq;
using DbLinq.SqlServer;

namespace dblinqExample
{
  [Table(Name="Products")]
  public class Product
  {
    [Column(Name="ProductID", IsPrimaryKey=true)]
    public int Id;

    [Column(Name="ProductName")]
    public string Name;

    [Column(Name="Price")]
    public decimal? Price;

    [Column(Name="ProductDescription")]
    public string Description;

    public override string ToString()
    {
      return "ID:" + Id + " NAME:" + Name + " PRICE:" + Price + " DESCRIPTION:" + Description;
    }
  }

  public class TestData : DataContext
  {
    public TestData(string constr)
      : base(new SqlConnection(constr), new SqlServerVendor())
    {
    }

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

  public class Program
  {
    public static void Main(string[] args)
    {
      string constr =
        "Data Source=192.168.1.x,49174;" +
        "Initial Catalog=TestData;" +
        "User ID=sta;" +
        "Password=passw0rd;" +
        "Trusted_Connection=False";

      TestData db = new TestData(constr);

      var results =
        from p in db.Products
        orderby p.Id
        select p;

      foreach (Product p in results)
      {
        Console.WriteLine(p);
      }
    }
  }
}
実行、問題ないようだ。

dblinq は SQL Server だけじゃなく、SQLite、PostgreSQL、MySQL、Oracle、Firebird、Ingres(!)と主要な RDBMS をサポートしていて、
LINQ TO SQLite だったら、次のような対応(DbLinq.Sqlite のビルド、接続文字列の変更も必要)で OK。
public class TestData : DataContext
{
  public TestData(string constr)
    : base(new Mono.Data.Sqlite.SqliteConnection(constr), new DbLinq.Sqlite.SqliteVendor())
  {
  }
...
実際のところ、LINQ TO SQL はうまくいかなかったのだけれど、結果オーライということで。

0 件のコメント:

コメントを投稿