2009年7月27日月曜日

LINQ TO NHibernate on Mono 2.4

まず、LINQ TO NHibernate(以下、L2NH)提供元 NHibernate.Linq(NHibernate.Linq.dll)で参照している System.Data.Services(System.Data.Services.dll)が、Mono 2.4 では実装されていないので、Mono 2.4(だけ)では L2NH を試すことはできない。

・・・では、「System.Data.Services.dll」があれば動くの?ということで Windows から拝借して、試してみた。

NHibernate.Linq ソース資源を svn checkout し、

$ svn co https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk/

MonoDevelop で NHibernate.Linq.sln を開いて、参照の修正(System.Data.Services)後、NHibernate.Linq をビルド。

試してみたコードはこれ。
  1. using System;  
  2. using System.Linq;  
  3. using NHibernate;  
  4. using NHibernate.Cfg;  
  5. using NHibernate.Linq;  
  6.   
  7. namespace NHibernateExample  
  8. {  
  9.   public class Product  
  10.   {  
  11.     int      _id;  
  12.     string   _name;  
  13.     decimal? _price;  
  14.     string   _description;  
  15.   
  16.     public virtual int Id  
  17.     {  
  18.       get { return _id; }  
  19.       set { _id = value; }  
  20.     }  
  21.   
  22.     public virtual string Name  
  23.     {  
  24.       get { return _name; }  
  25.       set { _name = value; }  
  26.     }  
  27.   
  28.     public virtual decimal? Price  
  29.     {  
  30.       get { return _price; }  
  31.       set { _price = value; }  
  32.     }  
  33.   
  34.     public virtual string Description  
  35.     {  
  36.       get { return _description; }  
  37.       set { _description = value; }  
  38.     }  
  39.   
  40.     public override string ToString()  
  41.     {  
  42.       return "ID:" + _id + " NAME:" + _name + " PRICE:" + _price + " DESCRIPTION:" + _description;  
  43.     }  
  44.   }  
  45.   
  46.   class Program  
  47.   {  
  48.     static void Main(string[] args)  
  49.     {  
  50.       Configuration cfg = new Configuration();  
  51.       cfg.Configure("SQLServer.cfg.xml");  
  52.       ISessionFactory factory = cfg.BuildSessionFactory();  
  53.   
  54.       using (ISession session = factory.OpenSession())  
  55.       {  
  56.         var results = from p in session.Linq<Product>()  
  57.                       orderby p.Id  
  58.                       select p;  
  59.   
  60.         foreach (Product p in results)  
  61.         {  
  62.           Console.WriteLine(p);  
  63.         }  
  64.       }  
  65.     }  
  66.   }  
  67. }  
  68. /* 
  69.  * Build: 
  70.  * 
  71.  *   gmcs -r:NHibernate.dll,NHibernate.Linq.dll l2nh.cs 
  72.  * 
  73.  * Run: 
  74.  * 
  75.  *   mono l2nh.exe 
  76.  * 
  77.  */  
コンフィグファイル(SQLServer.cfg.xml)
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2.   <hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >  
  3.   <session-factory name="NHibernateExample">  
  4.     <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>  
  5.     <property name="connection.connection_string">  
  6.       Data Source=192.168.1.*,49174;  
  7.       Initial Catalog=TestData;  
  8.       User ID=sta;  
  9.       Password=passw0rd;  
  10.       Trusted_Connection=False  
  11.     </property>  
  12.     <property name="adonet.batch_size">0</property>  
  13.     <property name="show_sql">false</property>  
  14.     <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>  
  15.     <property name="use_outer_join">true</property>  
  16.     <property name="command_timeout">60</property>  
  17.     <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>  
  18.     <property name="proxyfactory.factory_class">NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>  
  19.     <mapping file="Product.hbm.xml" />  
  20.   </session-factory>  
  21. </hibernate-configuration>  
マッピングファイル(Product.hbm.xml)
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"   
  3.   assembly="l2nh"  
  4.   namespace="NHibernateExample">  
  5.   
  6.   <class name="Product" table="Products">  
  7.     <id name="Id" column="ProductID">  
  8.       <generator class="assigned" />  
  9.     </id>  
  10.     <property name="Name" column="ProductName" not-null="true" />  
  11.     <property name="Price" column="Price" />  
  12.     <property name="Description" column="ProductDescription" />  
  13.   </class>  
  14.   
  15. </hibernate-mapping>  
実行(事前に NHibernate.Linq.dll、System.Data.Services.dll を MONO_PATH で設定してるディレクトリにコピー)。

$ gmcs -r:NHibernate.dll,NHibernate.Linq.dll l2nh.cs
$ mono l2nh.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:

うーむ、あっさりうまくいった。

NHibernate.Linq のビルドすら無警告で完了というくらい、無問題で試すことができたが、LINQ TO SQL と同様に、うまくいったとは言えない。

ただ、Windows から持ってきたアセンブリをそのまま使用してうまく動くということ自体、それはそれですごいことだよなと思う(当たり前すぎ?)。

それほどの基盤はあるが、あと一歩のところで、NotImplementedException をスローしたり、アセンブリそのものがなかったりと、らしいといえば、らしい。

今後、こういった Mono では未実装のアセンブリを Windows から持ってきて使用することに、実際どれくらいの障壁があるのか、また、案外そういった障壁が取り除かれて、使用無問題となったら、Mono が実装をカバーする領域って限定されたりするのかな。

0 件のコメント:

コメントを投稿