2009年7月8日水曜日

LINQ TO SQL on Mono 2.4

そういや、試してなかったな、ということでやってみた。

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

テーブルはいつものこれ。
  1. CREATE TABLE dbo.Products(  
  2.   ProductID int PRIMARY KEY NOT NULL,  
  3.   ProductName varchar(25) NOT NULL,  
  4.   Price money NULL,  
  5.   ProductDescription nvarchar(128) NULL)  
  6. GO  
試してみたコードはこれ。
  1. using System;  
  2. using System.Data.Linq;  
  3. using System.Data.Linq.Mapping;  
  4. using System.Linq;  
  5.   
  6. namespace SqlServerExample  
  7. {  
  8.   [Table(Name="Products")]  
  9.   public class Product  
  10.   {  
  11.     [Column(Name="ProductID", IsPrimaryKey=true)]  
  12.     public int Id;  
  13.   
  14.     [Column(Name="ProductName")]  
  15.     public string Name;  
  16.   
  17.     [Column(Name="Price")]  
  18.     public decimal? Price;  
  19.   
  20.     [Column(Name="ProductDescription")]  
  21.     public string Description;  
  22.   
  23.     public override string ToString()  
  24.     {  
  25.       return "ID:" + Id + " NAME:" + Name + " PRICE:" + Price + " DESCRIPTION:" + Description;  
  26.     }  
  27.   }  
  28.   
  29.   public class Program  
  30.   {  
  31.     public static void Main(string[] args)  
  32.     {  
  33.       string constr =  
  34.         "Data Source=192.168.1.x,49174;" +  
  35.         "Initial Catalog=TestData;" +  
  36.         "User ID=sta;" +  
  37.         "Password=passw0rd;" +  
  38.         "Trusted_Connection=False";  
  39.   
  40.       DataContext db = new DataContext(constr);  
  41.   
  42.       Table<Product> Products = db.GetTable<Product>();  
  43.   
  44.       var results =  
  45.         from p in Products  
  46.         orderby p.Id  
  47.         select p;  
  48.   
  49.       foreach (Product p in results)  
  50.       {  
  51.         Console.WriteLine(p);  
  52.       }  
  53.     }  
  54.   }  
  55. }  
実行。

$ 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 をビルド。

試してみたコードはこれ。
  1. using System;  
  2. using System.Data.Linq.Mapping;  
  3. using System.Data.SqlClient;  
  4. using System.Linq;  
  5.   
  6. using DbLinq.Data.Linq;  
  7. using DbLinq.SqlServer;  
  8.   
  9. namespace dblinqExample  
  10. {  
  11.   [Table(Name="Products")]  
  12.   public class Product  
  13.   {  
  14.     [Column(Name="ProductID", IsPrimaryKey=true)]  
  15.     public int Id;  
  16.   
  17.     [Column(Name="ProductName")]  
  18.     public string Name;  
  19.   
  20.     [Column(Name="Price")]  
  21.     public decimal? Price;  
  22.   
  23.     [Column(Name="ProductDescription")]  
  24.     public string Description;  
  25.   
  26.     public override string ToString()  
  27.     {  
  28.       return "ID:" + Id + " NAME:" + Name + " PRICE:" + Price + " DESCRIPTION:" + Description;  
  29.     }  
  30.   }  
  31.   
  32.   public class Program  
  33.   {  
  34.     public static void Main(string[] args)  
  35.     {  
  36.       string constr =  
  37.         "Data Source=192.168.1.x,49174;" +  
  38.         "Initial Catalog=TestData;" +  
  39.         "User ID=sta;" +  
  40.         "Password=passw0rd;" +  
  41.         "Trusted_Connection=False";  
  42.   
  43.         // 詳細  
  44.         //DbLinq.Data.Linq.DataContext db = new DbLinq.Data.Linq.DataContext(new SqlConnection(constr), new DbLinq.SqlServer.SqlServerVendor());  
  45.   
  46.         DataContext db = new DataContext(new SqlConnection(constr), new SqlServerVendor());  
  47.   
  48.         Table<Product> Products = db.GetTable<Product>();  
  49.   
  50.         var results =  
  51.           from p in Products  
  52.           orderby p.Id  
  53.           select p;  
  54.   
  55.         foreach (Product p in results)  
  56.         {  
  57.           Console.WriteLine(p);  
  58.         }  
  59.       }  
  60.     }  
  61.   }  
実行(事前に 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 っぽく、
  1. using System;  
  2. using System.Data.Linq.Mapping;  
  3. using System.Data.SqlClient;  
  4. using System.Linq;  
  5.   
  6. using DbLinq.Data.Linq;  
  7. using DbLinq.SqlServer;  
  8.   
  9. namespace dblinqExample  
  10. {  
  11.   [Table(Name="Products")]  
  12.   public class Product  
  13.   {  
  14.     [Column(Name="ProductID", IsPrimaryKey=true)]  
  15.     public int Id;  
  16.   
  17.     [Column(Name="ProductName")]  
  18.     public string Name;  
  19.   
  20.     [Column(Name="Price")]  
  21.     public decimal? Price;  
  22.   
  23.     [Column(Name="ProductDescription")]  
  24.     public string Description;  
  25.   
  26.     public override string ToString()  
  27.     {  
  28.       return "ID:" + Id + " NAME:" + Name + " PRICE:" + Price + " DESCRIPTION:" + Description;  
  29.     }  
  30.   }  
  31.   
  32.   public class TestData : DataContext  
  33.   {  
  34.     public TestData(string constr)  
  35.       : base(new SqlConnection(constr), new SqlServerVendor())  
  36.     {  
  37.     }  
  38.   
  39.     public Table<Product> Products  
  40.     {  
  41.       get { return GetTable<Product>(); }  
  42.     }  
  43.   }  
  44.   
  45.   public class Program  
  46.   {  
  47.     public static void Main(string[] args)  
  48.     {  
  49.       string constr =  
  50.         "Data Source=192.168.1.x,49174;" +  
  51.         "Initial Catalog=TestData;" +  
  52.         "User ID=sta;" +  
  53.         "Password=passw0rd;" +  
  54.         "Trusted_Connection=False";  
  55.   
  56.       TestData db = new TestData(constr);  
  57.   
  58.       var results =  
  59.         from p in db.Products  
  60.         orderby p.Id  
  61.         select p;  
  62.   
  63.       foreach (Product p in results)  
  64.       {  
  65.         Console.WriteLine(p);  
  66.       }  
  67.     }  
  68.   }  
  69. }  
実行、問題ないようだ。

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

0 件のコメント:

コメントを投稿