<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>.NET関連</title><link>http://blogs.wankuma.com/ganfield/category/1036.aspx</link><description>.NET関連</description><managingEditor>がんふぃーるど(ganfield@wankuma.com)</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>Oracle - Visual Studio and .NET Feature Requests</title><link>http://blogs.wankuma.com/ganfield/archive/2010/12/27/196063.aspx</link><pubDate>Mon, 27 Dec 2010 07:06:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2010/12/27/196063.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/196063.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2010/12/27/196063.aspx#Feedback</comments><slash:comments>287</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/196063.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/196063.aspx</trackback:ping><description>&lt;p&gt;Oracleに追加機能要求をできるページを発見。&lt;/p&gt; &lt;p&gt;&lt;a href="http://apex.oracle.com/pls/apex/f?p=18357:46"&gt;&lt;strong&gt;New Visual Studio and .NET Feature Request Tool - Vote for your Favorite Features!&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt; &lt;p&gt;見たところEntity Frameworkとシンドライバ（ODP.NET）はすでに2011年の計画に入っていたので、その下にあった「Support for Visual Studio Database Project」に一票投じておきました。SQL Serverではすでにありますが、データベースとプロジェクト間で構造を比較して差異を吸収するスクリプトを吐いてくれる機能は、開発時に重宝します。Visual Studio 2010ではPremium以上にしか付いてきませんが。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/196063.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>.NET Framework 4のメール送信機能</title><link>http://blogs.wankuma.com/ganfield/archive/2010/09/21/193131.aspx</link><pubDate>Tue, 21 Sep 2010 22:35:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2010/09/21/193131.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/193131.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2010/09/21/193131.aspx#Feedback</comments><slash:comments>243</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/193131.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/193131.aspx</trackback:ping><description>&lt;p&gt;一時期、DocomoやauでRCFに準拠していないメールアドレスが送信できないといった問題がありましたが、.NET Framework 4のSystem.Net.Mailでは送信できるようになっているんですね。  &lt;p&gt;MSDNのSystem.Net.Mail.MailAddressクラスの説明でも、「ユーザー名内の連続ドットと末尾のドット」が使用可能なメールアドレスの形式として明記されています。&lt;br&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/library/system.net.mail.mailaddress.aspx"&gt;http://msdn.microsoft.com/ja-jp/library/system.net.mail.mailaddress.aspx&lt;/a&gt; &lt;p&gt;&amp;nbsp; &lt;p&gt;実際にRadishというSMTP/POP3サーバを立てて試してみましたが、.NET Framework 4ではうまくいきました。（当然.NET Framework 2.0ではダメでした。） &lt;p&gt;&amp;nbsp; &lt;p&gt;RCFに準拠していないメールアドレスを新たに登録することは既に禁止されていますが、依然そのようなメールアドレスが残っている状態なので、日本のSIerとしては非常に助かります。&lt;br&gt;&lt;a href="http://www.nttdocomo.co.jp/info/spam_mail/measure/change_add/"&gt;http://www.nttdocomo.co.jp/info/spam_mail/measure/change_add/&lt;/a&gt;&lt;br&gt;&lt;a href="http://www.au.kddi.com/service/email/support/meiwaku/email_boshi/mail_address.html"&gt;http://www.au.kddi.com/service/email/support/meiwaku/email_boshi/mail_address.html&lt;/a&gt; &lt;p&gt;&amp;nbsp; &lt;p&gt;ちなみに、SmtpClientにも変更があり、SmtpClientクラスが新たにIDisposableを実装しています。MSDNの説明を見るとFinalizeメソッドが無いのでしっかりとDisposeを呼び出してアンマネージリソースを解放する必要があるそうな。&lt;br&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/library/system.net.mail.smtpclient.aspx"&gt;http://msdn.microsoft.com/ja-jp/library/system.net.mail.smtpclient.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/193131.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>NHibernate.Linqでデータアクセス - Eager Loading編</title><link>http://blogs.wankuma.com/ganfield/archive/2009/09/23/181546.aspx</link><pubDate>Wed, 23 Sep 2009 02:10:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/09/23/181546.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/181546.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/09/23/181546.aspx#Feedback</comments><slash:comments>220</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/181546.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/181546.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://blogs.wankuma.com/ganfield/archive/2009/09/22/181525.aspx"&gt;前回&lt;/A&gt;に続いてNHibernate.Linqの続き。&lt;/P&gt;
&lt;P&gt;NHibernateは構成情報でFactoryの設定をちゃんと行えば、NHibernateのセッション内でLazy Loadingを行います。ただしセッション外ではLazy Loadingが効かないので、データをロードしていないプロパティにアクセスすると、例外が発生してしまいます。これを解消するために、予めデータを読み込んでおくEager Loadingを行います。&lt;/P&gt;
&lt;H4&gt;NHibernate.LinqでEager Loading&lt;/H4&gt;
&lt;P&gt;NHibernate.LinqのメソッドExpand(string)を使用します。機能としてはEntity FrameworkのInclude(string)とほぼ同じです。加えて、INHibernateQueryable&lt;T&gt;.QueryOptions.RegisterCustomActionメソッドを使用して、内部のCriteriaオブジェクトにDistinctRootEntityResultTransformerを使用するように設定します。Transformerを設定しない場合、1:Nの関連にあるオブジェクトをEager Loadingすると返却されるルートオブジェクトのカーディナリティがN側に引きずられてしまいます。&lt;/P&gt;
&lt;P&gt;例えば、EmployeeID=1の従業員(Employees)の管轄区域（Territories）が3つある場合、従業員(Employees)オブジェクトをルートオブジェクトとし、管轄区域(Territories)オブジェクトをEager LoadingしようとするとEmployeeID=1のEmployeesオブジェクトが3つ返ってきてしまいます。本来、EmployeeID=1のEmployeesオブジェクトは1つ返ってくるだけでよいので、この部分の挙動を変更するためのDistinctRootEntityResultTransformerを設定します。&lt;/P&gt;&lt;PRE class=C# name="code"&gt;private IList&lt;EMPLOYEES&gt; GetEmployeesWithEagerLoading(decimal departmentId)
{
    using (ISession session = factory.OpenSession())
    {
        var empQuery = session.Linq&lt;EMPLOYEES&gt;();
        empQuery.QueryOptions.RegisterCustomAction(s =&amp;gt; s.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer()));

        var empList = from emps in empQuery.Expand("ListEmployeeterritories")
                      where emps.Department.Departmentid == departmentId
                      select emps;

        return empList.ToList&lt;EMPLOYEES&gt;();
    }
}&lt;/PRE&gt;
&lt;P&gt;Transformerを指定しないとダメってのが意外に忘れがちですが、全然難しくないですよね。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/181546.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>NHibernate.Linqでデータアクセス</title><link>http://blogs.wankuma.com/ganfield/archive/2009/09/22/181525.aspx</link><pubDate>Tue, 22 Sep 2009 00:06:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/09/22/181525.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/181525.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/09/22/181525.aspx#Feedback</comments><slash:comments>237</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/181525.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/181525.aspx</trackback:ping><description>&lt;p&gt;&lt;a href="http://sourceforge.net/projects/nhibernate/files/"&gt;NHibernate.Linq 1.0.0 GA&lt;/a&gt; が2カ月ほど前にリリースされました。リファレンス読んでから記事にしようかな～と思いつつ、早2ヶ月。リファレンスが来ない！＞＜&lt;/p&gt; &lt;p&gt;NHibernateは、Linqを実装しているORMの中でも、複数のデータベースに対応しつつ、Native SQLを発行できる数少ないORMです。Linqとは若干離れますが、動的にSQLを組む必要があるとき（表示するデータは少ないけど、データを絞り込むために必要なデータが広大な場合など）のパフォーマンスチューニングがやり易いので、日本語ドキュメントが少ないながらも使えるんじゃないかと思っています。日本語ドキュメントがほしければ、本家Hibernateのものならかなりあるし。&lt;/p&gt; &lt;p&gt;せっかくなので、NHibernate.LinqのソースのTestプロジェクトを参考にしつつ、Oracleでざっくり試用してみました。&lt;/p&gt; &lt;h4&gt;NHibernate.Linq概要&lt;/h4&gt; &lt;p&gt;Criteria APIにマップしているだけみたいなので、Criteria APIにできることは大体できるようです。（ということは、1:Nのマッピングなども大丈夫なはず）&lt;/p&gt; &lt;h4&gt;テーブル&lt;/h4&gt; &lt;p&gt;&lt;a href="http://www.codeplex.com/dbmodelexcel"&gt;Database Modelling Excel&lt;/a&gt;を使用して作成。FKも定義できるから楽ですよね。テーブル定義書という、ドキュメントとしては足りないものがいくつかあるがががが。&lt;/p&gt;&lt;pre class="sql" name="code"&gt;CREATE TABLE Employees (
   EmployeeID number(10,0) NOT NULL 
  ,LastName varchar2(50) NOT NULL 
  ,FirstName varchar2(50) NOT NULL 
  ,DepartmentID number(4,0) NOT NULL 
  ,SupervisorID number(10,0) NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE Employees ADD CONSTRAINT PK_Employees PRIMARY KEY (EmployeeID);

CREATE TABLE EmployeeTerritories (
   EmployeeTerritoryID number(10,0) NOT NULL 
  ,EmployeeID number(10,0) NOT NULL 
  ,TerritoryID number(10,0) NOT NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE EmployeeTerritories ADD CONSTRAINT PK_EmployeeTerritories PRIMARY KEY (EmployeeTerritoryID);

CREATE TABLE Territories (
   TerritoryID number(10,0) NOT NULL 
  ,TerritoryDescription varchar2(50) NOT NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE Territories ADD CONSTRAINT PK_Territories PRIMARY KEY (TerritoryID);

CREATE TABLE EmployeeResume (
   EmployeeResumeID number(10,0) NOT NULL 
  ,ResumeDescription varchar2(50) NOT NULL 
  ,EmployeeID number(10,0) NOT NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE EmployeeResume ADD CONSTRAINT PK_EmployeeResume PRIMARY KEY (EmployeeResumeID);

CREATE TABLE EmployeeCerts (
   EmployeeCertID number(10,0) NOT NULL 
  ,CertificationName varchar2(50) NOT NULL 
  ,EmployeeID number(10,0) NOT NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE EmployeeCerts ADD CONSTRAINT PK_EmployeeCerts PRIMARY KEY (EmployeeCertID);

CREATE TABLE EmployeeCertDetails (
   EmployeeCertDetailID number(10,0) NOT NULL 
  ,ExamName varchar2(50) NOT NULL 
  ,EmployeeCertID number(10,0) NOT NULL 
  ,ExamDate Date NOT NULL 
  ,IsPassed Number(1,0) NOT NULL 
  ,ExamFee Number(8,0) NOT NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE EmployeeCertDetails ADD CONSTRAINT PK_EmployeeCertDetails PRIMARY KEY (EmployeeCertDetailID);

CREATE TABLE Departments (
   DepartmentID number(10,0) NOT NULL 
  ,DepartmentName varchar2(50) NOT NULL 
  ,LastModifiedDate timestamp(9) NOT NULL 
  ,LastModifiedUser varchar2(20) NOT NULL 
);
ALTER TABLE Departments ADD CONSTRAINT PK_Departments PRIMARY KEY (DepartmentID);

ALTER TABLE Employees ADD CONSTRAINT FK_Employees_SupervisorID
  FOREIGN KEY (SupervisorID) REFERENCES Employees(EmployeeID);
ALTER TABLE Employees ADD CONSTRAINT FK_Employees_DepartmentID
  FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID);

ALTER TABLE EmployeeTerritories ADD CONSTRAINT FK_EmployeeTerritories_Emp0000
  FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID);
ALTER TABLE EmployeeTerritories ADD CONSTRAINT FK_EmployeeTerritories_Ter0000
  FOREIGN KEY (TerritoryID) REFERENCES Territories(TerritoryID);

ALTER TABLE EmployeeResume ADD CONSTRAINT FK_EmployeeResume_EmployeeID
  FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID);

ALTER TABLE EmployeeCerts ADD CONSTRAINT FK_EmployeeCerts_EmployeeID
  FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID);

ALTER TABLE EmployeeCertDetails ADD CONSTRAINT FK_EmployeeCertDetails_Emp0000
  FOREIGN KEY (EmployeeCertID) REFERENCES EmployeeCerts(EmployeeCertID);&lt;/pre&gt;
&lt;p&gt;今回試用するのはEmployeesテーブルとDepartmentsテーブルのみ。そのほかのテーブルは1:Nなどのマッピングを試すために作成したもので、今回は使用していません。&lt;/p&gt;
&lt;h4&gt;エンティティ&lt;/h4&gt;
&lt;p&gt;コードはMyGeneration1.3のNHibernate Object Mapping 1.3.1テンプレートを使って自動生成したものを修正して使用しています。&lt;/p&gt;
&lt;p&gt;Employees.cs&lt;/p&gt;&lt;pre class="c#" name="code"&gt;using System;
using System.Collections;
using System.Collections.Generic;

namespace NHSampleEntity.Entities
{
	/// &lt;summary&gt;
	/// Generated by MyGeneration using the NHibernate Object Mapping 1.3.1 by Grimaldi Giuseppe (giuseppe.grimaldi@infracom.it)
	/// &lt;/summary&gt;
	[Serializable]
	public class Employees 
	{
		#region Private Members
		
		// Variabili di stato
		private bool _isChanged;
		private bool _isDeleted;

		// Primary Key(s) 
		private decimal _employeeid; 
		
		// Foreign Keys mappate come Many-To-One 
		private Departments _departmentid; 
		private Employees _supervisorid; 
		
		// Properties 
		private string _lastname; 
		private string _firstname; 
		private DateTime _lastmodifieddate; 
		private string _lastmodifieduser; 
		
		// One-to-many relations 
		private IList&lt;employeecerts&gt; _listEmployeecerts;
		private IList&lt;employeeresume&gt; _listEmployeeresume;
		private IList&lt;employees&gt; _listEmployees;
		private IList&lt;employeeterritories&gt; _listEmployeeterritories;		

		#endregion
		
		#region Default ( Empty ) Class Constructor
		
		/// &lt;summary&gt;
		/// default constructor
		/// &lt;/summary&gt;
		public Employees()
		{
			_employeeid = 0; 
			_departmentid = null; 
			_supervisorid = null; 
			_lastname = null; 
			_firstname = null; 
			_lastmodifieddate = DateTime.MinValue; 
			_lastmodifieduser = null; 
			_listEmployeecerts = null; 
			_listEmployeeresume = null; 
			_listEmployees = null; 
			_listEmployeeterritories = null; 
		}
		
		#endregion // End of Default ( Empty ) Class Constructor
		
		#region Full Constructor
		
		/// &lt;summary&gt;
		/// full constructor
		/// &lt;/summary&gt;
		public Employees(decimal employeeid, Departments departmentid, Employees supervisorid, string lastname, string firstname, DateTime lastmodifieddate, string lastmodifieduser)
		{
			_employeeid = employeeid; 
			_departmentid = departmentid; 
			_supervisorid = supervisorid; 
			_lastname = lastname; 
			_firstname = firstname; 
			_lastmodifieddate = lastmodifieddate; 
			_lastmodifieduser = lastmodifieduser; 
			_listEmployeecerts = null; 
			_listEmployeeresume = null; 
			_listEmployees = null; 
			_listEmployeeterritories = null; 
		}
		
		#endregion // End Full Constructor
		
		#region Required Fields Only Constructor
		
		/// &lt;summary&gt;
		/// required (not null) fields only constructor
		/// &lt;/summary&gt;
		public Employees(decimal employeeid, Departments departmentid, string lastname, string firstname, DateTime lastmodifieddate, string lastmodifieduser)
		{
			_employeeid = employeeid; 
			_departmentid = departmentid; 
			_supervisorid = null; 
			_lastname = lastname; 
			_firstname = firstname; 
			_lastmodifieddate = lastmodifieddate; 
			_lastmodifieduser = lastmodifieduser; 
			_listEmployeecerts = null; 
			_listEmployeeresume = null; 
			_listEmployees = null; 
			_listEmployeeterritories = null; 
		}
		
		#endregion // End Required Fields Only Constructor

		#region Public Properties
			
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual decimal Employeeid
		{
			get { return _employeeid; }
			set { _isChanged |= (_employeeid != value); _employeeid = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual Departments Department
		{
			get { return _departmentid; }
			set { _isChanged |= (_departmentid != value); _departmentid = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual Employees Supervisor
		{
			get { return _supervisorid; }
			set { _isChanged |= (_supervisorid != value); _supervisorid = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual string Lastname
		{
			get { return _lastname; }
			set	
			{
				if ( value != null )
					if( value.Length &amp;gt; 50)
						throw new ArgumentOutOfRangeException("Invalid value for Lastname", value, value.ToString());
				
				_isChanged |= (_lastname != value); _lastname = value;
			}
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual string Firstname
		{
			get { return _firstname; }
			set	
			{
				if ( value != null )
					if( value.Length &amp;gt; 50)
						throw new ArgumentOutOfRangeException("Invalid value for Firstname", value, value.ToString());
				
				_isChanged |= (_firstname != value); _firstname = value;
			}
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual DateTime Lastmodifieddate
		{
			get { return _lastmodifieddate; }
			set { _isChanged |= (_lastmodifieddate != value); _lastmodifieddate = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual string Lastmodifieduser
		{
			get { return _lastmodifieduser; }
			set	
			{
				if ( value != null )
					if( value.Length &amp;gt; 20)
						throw new ArgumentOutOfRangeException("Invalid value for Lastmodifieduser", value, value.ToString());
				
				_isChanged |= (_lastmodifieduser != value); _lastmodifieduser = value;
			}
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual IList&lt;employeecerts&gt; ListEmployeecerts
		{
			get { return _listEmployeecerts; }
			set { _isChanged |= (_listEmployeecerts != value); _listEmployeecerts = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual IList&lt;employeeresume&gt; ListEmployeeresume
		{
			get { return _listEmployeeresume; }
			set { _isChanged |= (_listEmployeeresume != value); _listEmployeeresume = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual IList&lt;employees&gt; ListEmployees
		{
			get { return _listEmployees; }
			set { _isChanged |= (_listEmployees != value); _listEmployees = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual IList&lt;employeeterritories&gt; ListEmployeeterritories
		{
			get { return _listEmployeeterritories; }
			set { _isChanged |= (_listEmployeeterritories != value); _listEmployeeterritories = value; }
		} 
	  
		/// &lt;summary&gt;
		/// Returns whether or not the object has changed it's values.
		/// &lt;/summary&gt;
		public virtual bool IsChanged
		{
			get { return _isChanged; }
		}
		
		/// &lt;summary&gt;
		/// Returns whether or not the object has changed it's values.
		/// &lt;/summary&gt;
		public virtual bool IsDeleted
		{
			get { return _isDeleted; }
		}
		
		#endregion 
		
		#region Public Functions

		/// &lt;summary&gt;
		/// mark the item as deleted
		/// &lt;/summary&gt;
		public virtual void MarkAsDeleted()
		{
			_isDeleted = true;
			_isChanged = true;
		}
		
		#endregion
	}
}
&lt;/pre&gt;
&lt;p&gt;Departments.cs&lt;/p&gt;&lt;pre class="c#" name="code"&gt;using System;
using System.Collections;
using System.Collections.Generic;

namespace NHSampleEntity.Entities
{
	/// &lt;summary&gt;
	/// Generated by MyGeneration using the NHibernate Object Mapping 1.3.1 by Grimaldi Giuseppe (giuseppe.grimaldi@infracom.it)
	/// &lt;/summary&gt;
	[Serializable]
	public class Departments 
	{
		#region Private Members
		
		// Variabili di stato
		private bool _isChanged;
		private bool _isDeleted;

		// Primary Key(s) 
		private decimal _departmentid; 
		
		// Properties 
		private string _departmentname; 
		private DateTime _lastmodifieddate; 
		private string _lastmodifieduser; 
		
		// One-to-many relations 
		private IList&lt;employees&gt; _listEmployees;		

		#endregion
		
		#region Default ( Empty ) Class Constructor
		
		/// &lt;summary&gt;
		/// default constructor
		/// &lt;/summary&gt;
		public Departments()
		{
			_departmentid = 0; 
			_departmentname = null; 
			_lastmodifieddate = DateTime.MinValue; 
			_lastmodifieduser = null; 
			_listEmployees = null; 
		}
		
		#endregion // End of Default ( Empty ) Class Constructor
		
		#region Full Constructor
		
		/// &lt;summary&gt;
		/// full constructor
		/// &lt;/summary&gt;
		public Departments(decimal departmentid, string departmentname, DateTime lastmodifieddate, string lastmodifieduser)
		{
			_departmentid = departmentid; 
			_departmentname = departmentname; 
			_lastmodifieddate = lastmodifieddate; 
			_lastmodifieduser = lastmodifieduser; 
			_listEmployees = null; 
		}
		
		#endregion // End Full Constructor

		#region Public Properties
			
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual decimal Departmentid
		{
			get { return _departmentid; }
			set { _isChanged |= (_departmentid != value); _departmentid = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual string Departmentname
		{
			get { return _departmentname; }
			set	
			{
				if ( value != null )
					if( value.Length &amp;gt; 50)
						throw new ArgumentOutOfRangeException("Invalid value for Departmentname", value, value.ToString());
				
				_isChanged |= (_departmentname != value); _departmentname = value;
			}
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual DateTime Lastmodifieddate
		{
			get { return _lastmodifieddate; }
			set { _isChanged |= (_lastmodifieddate != value); _lastmodifieddate = value; }
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual string Lastmodifieduser
		{
			get { return _lastmodifieduser; }
			set	
			{
				if ( value != null )
					if( value.Length &amp;gt; 20)
						throw new ArgumentOutOfRangeException("Invalid value for Lastmodifieduser", value, value.ToString());
				
				_isChanged |= (_lastmodifieduser != value); _lastmodifieduser = value;
			}
		} 
	  
		/// &lt;summary&gt;
		/// 
		/// &lt;/summary&gt;		
		public virtual IList&lt;employees&gt; ListEmployees
		{
			get { return _listEmployees; }
			set { _isChanged |= (_listEmployees != value); _listEmployees = value; }
		} 
	  
		/// &lt;summary&gt;
		/// Returns whether or not the object has changed it's values.
		/// &lt;/summary&gt;
		public virtual bool IsChanged
		{
			get { return _isChanged; }
		}
		
		/// &lt;summary&gt;
		/// Returns whether or not the object has changed it's values.
		/// &lt;/summary&gt;
		public virtual bool IsDeleted
		{
			get { return _isDeleted; }
		}
		
		#endregion 
		
		#region Public Functions

		/// &lt;summary&gt;
		/// mark the item as deleted
		/// &lt;/summary&gt;
		public virtual void MarkAsDeleted()
		{
			_isDeleted = true;
			_isChanged = true;
		}
		
		#endregion
	}
}
&lt;/pre&gt;
&lt;h4&gt;NHibernate.Linq実行コード&lt;/h4&gt;
&lt;p&gt;using NHibertnate.Linqを一行追加して、次のコードでデータアクセス可能となります。&lt;/p&gt;&lt;pre class="c#" name="code"&gt;        private ISession _session;

        public Form1()
        {
            InitializeComponent();

            Configuration cfg = new Configuration();
            cfg.Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "hibernate.cfg.xml"));
            cfg.AddAssembly(typeof(Employees).Assembly);
            ISessionFactory factory = cfg.BuildSessionFactory();
            _session = factory.OpenSession();
        }

        private IList&lt;employees&gt; GetEmployees(decimal departmentId)
        {
            var empList = from emps in _session.Linq&lt;employees&gt;()
                          where emps.Department.Departmentid == departmentId
                          select emps;

            return empList.ToList&lt;employees&gt;();
        }&lt;/pre&gt;
&lt;p&gt;EmployeesのDepartmentIDが任意のEmployeesオブジェクトコレクションを返却してくれます。NHibernate本体を2.1にアップグレードできるのであれば、既存コードそのままにNHibernate.Linqを導入できます。&lt;/p&gt;
&lt;p&gt;HQLやCriteria APIはあまり好きじゃないけど、NHibernate.Linqはええかも。VisualStudio2010であれば、EDMのコード生成機能をFluent NHibernateと組み合わせて使えばEDMをNHibernate用のDSLツールとしても利用できそうですし。夢が膨らむー。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/181525.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ODP.NET 11.1.0.7.20 リリース</title><link>http://blogs.wankuma.com/ganfield/archive/2009/09/17/181333.aspx</link><pubDate>Thu, 17 Sep 2009 12:21:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/09/17/181333.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/181333.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/09/17/181333.aspx#Feedback</comments><slash:comments>688</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/181333.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/181333.aspx</trackback:ping><description>&lt;P&gt;新しいODP.NET（英語）がリリースされています。日本語の方はまだ11.1.0.7.10 betaですがｗ&lt;/P&gt;
&lt;P&gt;New .NET Features for Oracle Database&lt;BR&gt;&lt;A href="http://www.oracle.com/technology/tech/windows/odpnet/newfeatures.html"&gt;http://www.oracle.com/technology/tech/windows/odpnet/newfeatures.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Oracle Data Access Components (ODAC) Downloads&lt;BR&gt;&lt;A href="http://www.oracle.com/technology/software/tech/windows/odpnet/index.html"&gt;http://www.oracle.com/technology/software/tech/windows/odpnet/index.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Oracle Data Provider for .NET Documentation&lt;BR&gt;&lt;A href="http://www.oracle.com/technology/docs/tech/windows/odpnet/index.html"&gt;http://www.oracle.com/technology/docs/tech/windows/odpnet/index.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;New Featureは11.1.0.7.10と変わってないように見えますね。&lt;/P&gt;
&lt;P&gt;しかし、System Requirementsに&lt;BR&gt;32-bit: Windows Vista (Business, Enterprise, and Ultimate Editions), Windows Server 2008, Windows Server 2003, Windows Server 2003 R2, Windows 2000 or Windows XP Professional Edition.&lt;BR&gt;Oracle supports 32-bit ODP.NET on x86, AMD64, and Intel EM64T processors on these operating systems.&lt;/P&gt;
&lt;P&gt;64 bit: Windows Vista x64 (Business, Enterprise, and Ultimate Editions), Windows Server 2008 x64, Windows Server 2003 x64, Windows Server 2003 R2 x64, or Windows XP x64.&lt;BR&gt;Oracle supports 32-bit ODP.NET and 64-bit ODP.NET for Windows x64 on these operating systems.&lt;/P&gt;
&lt;P&gt;やった！Windows Server 2008 x64がサポートされた！&lt;BR&gt;&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/181333.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>ReportViewerコントロールでSystem.EntryPointNotFoundException</title><link>http://blogs.wankuma.com/ganfield/archive/2009/08/26/180508.aspx</link><pubDate>Wed, 26 Aug 2009 06:51:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/08/26/180508.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/180508.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/08/26/180508.aspx#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/180508.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/180508.aspx</trackback:ping><description>&lt;P&gt;ASP.NETのReportViewerコントロールにて、IReportServerCredentialを実装してWindows統合認証でレポートサーバにアクセスしたら次の例外が発生&lt;/P&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=1 width=672&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=670&gt;
&lt;P&gt;2009/08/25 11:12:39 エントリ ポイントが見つかりませんでした。&lt;BR&gt;System.EntryPointNotFoundException&lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 Microsoft.Reporting.WebForms.IReportServerCredentials.get_NetworkCredentials()&lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 Microsoft.Reporting.WebForms.ServerReport.get_ServerNetworkCredentials()&lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 Microsoft.Reporting.WebForms.ServerReport.get_Service()&lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 Microsoft.Reporting.WebForms.ServerReport.GetExecutionInfo()&lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 Microsoft.Reporting.WebForms.ServerReport.SetParameters(IEnumerable`1 parameters)&lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 XXXPage.OnPreRender(EventArgs e) &lt;BR&gt;&amp;nbsp;&amp;nbsp; 場所 System.Web.UI.Control.PreRenderRecursiveInternal()&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;原因は、参照しているMicrosoft.Reporting.WebForms.dllのバージョンが古い（8.0）ことでした。Visual Studio 2005で開発したときの参照がそのまま残っており、Visual Studio 2008で開発したWebアプリケーションが使用しているMicrosoft.Reporting.WebForms.dllのバージョン（9.0）と合ってませんでした。&lt;/P&gt;
&lt;P&gt;コンパイルエラーにもならず、実行時に例外が出るもんだからバージョンが誤っていることに気づくまで、かなり時間を要しました。「プロパティのGetterでエラーって何？」なんてことを無駄に深読みしつつ数時間・・・ははは（自嘲気味ｗ&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/180508.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>Team Foundation Serverの作業項目の高さを調整</title><link>http://blogs.wankuma.com/ganfield/archive/2009/07/31/179595.aspx</link><pubDate>Fri, 31 Jul 2009 06:43:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/07/31/179595.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/179595.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/07/31/179595.aspx#Feedback</comments><slash:comments>298</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/179595.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/179595.aspx</trackback:ping><description>&lt;p&gt;作業項目のコントロールの高さを指定する方法です。独自の作業項目を作成していたら、TFS 2005とTFS 2008で異なっていた、というかTFS 2005の場合はドキュメントに記載されていない、のでメモ書き程度に。&lt;/p&gt; &lt;h4&gt;TFS 2008の場合&lt;/h4&gt; &lt;p&gt;&amp;lt;Control FieldName=”fieldName” Type=”type” Lable=”label” LabelPosition=”Left” &lt;font color="#ff0000"&gt;MinimumSize=”(150,100)”&lt;/font&gt; /&amp;gt;&lt;/p&gt; &lt;p&gt;括弧あり&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h4&gt;TFS 2005の場合&lt;/h4&gt; &lt;p&gt;&amp;lt;Control FieldName=”fieldName” Type=”type” Lable=”label” LabelPosition=”Left” &lt;font color="#ff0000"&gt;MinimumSize=”150,100”&lt;/font&gt; /&amp;gt;&lt;/p&gt; &lt;p&gt;括弧なし&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;MinimumSizeがMSDNのマニュアルに記載されたのはTFS 2008からですが、TFS 2005でも使用することはできます。ただし、記法に若干の違いが見られる通り、使用は自己責任で。また、TFS 2005⇒TFS 2008移行時にプロセステンプレートをアップロードしてMinimumSize関連でエラーが出たら、疑ってみてください。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;参考&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/ja-jp/library/aa337625.aspx"&gt;Control 要素 (作業項目の種類の定義スキーマ)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/vstsblog/archive/2007/07/07/undocumented-attributes-for-controlling-the-work-item-form-layout.aspx"&gt;Undocumented attributes for controlling the Work Item form layout&lt;/a&gt;&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/179595.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>Merge文とExecuteNonQueryとSQLServerとOracle 時々バグ？ 回避策</title><link>http://blogs.wankuma.com/ganfield/archive/2009/05/25/173574.aspx</link><pubDate>Mon, 25 May 2009 21:37:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/05/25/173574.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/173574.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/05/25/173574.aspx#Feedback</comments><slash:comments>584</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/173574.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/173574.aspx</trackback:ping><description>&lt;P&gt;とある戦国時代の武将がこう言ってました。&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;鳴かぬのなら、&lt;FONT color=#c0c0c0&gt;&lt;STRIKE&gt;殺してしまおう&lt;/STRIKE&gt;&lt;/FONT&gt;鳴かせて見せよう、とほほぎす&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;色々と引用文に間違いがありますが、&lt;A href="http://blogs.wankuma.com/ganfield/archive/2009/05/23/173492.aspx"&gt;前回&lt;/A&gt;と&lt;A href="http://blogs.wankuma.com/ganfield/archive/2009/05/23/173465.aspx"&gt;前々回&lt;/A&gt;の続きです。&lt;/P&gt;
&lt;P&gt;まず、他のバージョンの組み合わせに関してですが、前回のコメントでやじゅさんがおっしゃった通り、どうもODP.NET 10.2でも発生するみたいです。&lt;/P&gt;
&lt;P&gt;Merge文使われてないのかな～なんて思いつつも、Oracleの対応を待つのも何なので、回避策を書いておこうと思います。&lt;/P&gt;
&lt;H4&gt;回避策：大人しくSystem.Data.OracleClientを使用する&lt;/H4&gt;
&lt;P&gt;半分冗談です＾＾&lt;/P&gt;
&lt;P&gt;次が本当の回避策です。&lt;/P&gt;
&lt;H4&gt;&lt;/H4&gt;
&lt;H4&gt;本当の回避策：無名ブロックとRAISE_APPLICATION_ERRORを使用する&lt;/H4&gt;
&lt;P&gt;無名ブロックというのは、ストアドされないただのプロシージャで、BEGIN～ENDで囲まれているPL/SQLです。&lt;/P&gt;
&lt;P&gt;考え方として、次のような感じになります。&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;無名ブロック内でMerge文を発行 
&lt;LI&gt;SQL%ROWCOUNTが0であれば、楽観ロック発生としRAISE_APPLICATION_ERRORで例外を挙げる&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;最後にある「RAISE_APPLICATION_ERROR」は、開発者が任意のSQLCODE（いわゆるORA-XXXXXのXXXXX部分）と任意のメッセージを返すことができるものです。&lt;/P&gt;
&lt;P&gt;RAISE_APPLICATION_ERRORについては「&lt;A href="http://www.shift-the-oracle.com/"&gt;SHIFT the Oracle&lt;/A&gt;」内の「&lt;A href="http://www.shift-the-oracle.com/plsql/exception/raise_application_error.html"&gt;RAISE_APPLICATION_ERROR&lt;/A&gt;」に分かり易く解説されています。&lt;/P&gt;
&lt;P&gt;ということで、SQL&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:812469c5-0cb0-4c63-8c15-c81123a09de7:051c7108-6d92-4975-9d7a-c07d91d03f5d class=wlWriterEditableSmartContent&gt;&lt;PRE class=sql name="code"&gt;BEGIN
  --MERGE実行
  MERGE INTO MergeTable Target
  USING (SELECT :key1 Key1, :col1 Col1, :col2 Col2, :optLock OptLock
    FROM DUAL) InputSrc
  ON (Target.Key1 = InputSrc.Key1)
  WHEN MATCHED THEN
    UPDATE SET
      Col1 = InputSrc.Col1
      , Col2 = InputSrc.Col2
    WHERE Target.OptLock = InputSrc.OptLock
  WHEN NOT MATCHED THEN
    INSERT (Key1, Col1, Col2, OptLock)
      VALUES (InputSrc.Key1, InputSrc.Col1, InputSrc.Col2, systimestamp);

  --件数チェック（楽観ロックに引っかかった場合は0）
  IF SQL%ROWCOUNT = 0 THEN
    RAISE_APPLICATION_ERROR(-20801, '楽観的過ぎて更新できませんでした＞＜');
  END IF;
END;&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;18行目の-20801ですが、この部分がOracleException.Numberに入ってきます。ただし、.NET側では正の数で入ってくるので、OracleException.Numberが20801のときに、OptimisticConcurrencyExceptionにラップするなりなんなりして下さい。&lt;/P&gt;
&lt;P&gt;ちなみに、ORA-20000～ORA-20999がユーザ定義のSQLCODEとしてOracleが許可している範囲ですが、他のOracleのアプリケーションでも使用されています。実際、ORA-20000あたりがOracleTextを使用していたときに発生した記憶があります。&lt;/P&gt;
&lt;P&gt;SHIFT the Oracleの説明にもありますが、ORA-20000～ORA-20999がユーザ定義のSQLCODEとして許可されているものの、被らないという保証は一切ありません。なので、仕事で使用する場合はMessageの部分に独自のエラーコードを付与し、.NET側ではOracleException.Numberと共にOracleException.Messageも同様に調べ、適切に処理する方が良いと思います。&lt;/P&gt;
&lt;P&gt;コード&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:812469c5-0cb0-4c63-8c15-c81123a09de7:17495b21-3900-4a7d-b781-812beca80c27 class=wlWriterEditableSmartContent&gt;&lt;PRE class=c# name="code"&gt;const string sql
= @"BEGIN
  --MERGE実行
  MERGE INTO MergeTable Target
  USING (SELECT :key1 Key1, :col1 Col1, :col2 Col2, :optLock OptLock
    FROM DUAL) InputSrc
  ON (Target.Key1 = InputSrc.Key1)
  WHEN MATCHED THEN
    UPDATE SET
      Col1 = InputSrc.Col1
      , Col2 = InputSrc.Col2
    WHERE Target.OptLock = InputSrc.OptLock
  WHEN NOT MATCHED THEN
    INSERT (Key1, Col1, Col2, OptLock)
      VALUES (InputSrc.Key1, InputSrc.Col1, InputSrc.Col2, systimestamp);

  --件数チェック（楽観ロックに引っかかった場合は0）
  IF SQL%ROWCOUNT = 0 THEN
    RAISE_APPLICATION_ERROR(-20801, 'ERR-001:楽観的過ぎて更新できませんでした＞＜');
  END IF;
END;";

private void ExecuteMergeSql()
{
    OracleConnection conn = new OracleConnection("user id=xxx;password=yyy;data source=zzz");
    try
    {
        conn.Open();
        OracleCommand command = conn.CreateCommand();
        command.BindByName = true;
        command.CommandText = sql.Replace("\r", ""); //CRLFをLFだけに修正
        command.Parameters.Add(new OracleParameter("key1", 4));
        command.Parameters.Add(new OracleParameter("col1", "aaa"));
        command.Parameters.Add(new OracleParameter("col2", "bbb"));
        command.Parameters.Add(new OracleParameter("optLock", DateTime.Now));

        command.ExecuteNonQuery();
    }
    catch (OracleException oex)
    {
        if (oex.Number == 20801)
        {
            // ここで楽観ロックエラーを処理
        }
        else
        {
            throw;
        }
    }
    finally 
    {
        conn.Close();
    }
}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;最後に、Oracleで無名ブロックを使用する場合の注意点ですが、環境によってBEGIN～ENDの間の&lt;A href="http://blogs.wankuma.com/ganfield/archive/2008/09/16/156709.aspx"&gt;改行コードをLFだけにしなければならない場合&lt;/A&gt;があります。（31行目の部分）&lt;/P&gt;
&lt;P&gt;これを行わないと、次のようなエラーが表示されます。&lt;/P&gt;
&lt;BLOCKQUOTE&gt;Oracle.DataAccess.Client.OracleException ORA-06550: 行1、列6:&lt;BR&gt;PLS-00103: 記号""が見つかりました。 次のうちの1つが入るとき:&lt;BR&gt;begin case declare exit for goto if loop mod null pragma&lt;BR&gt;raise return select update while with ＜an identifier＞&lt;BR&gt;＜a double-quoted delimited-identifier＞ ＜a bind variable＞ ＜＜&lt;BR&gt;close current delete fetch lock insert open rollback&lt;BR&gt;savepoint set sql execute commit forall merge pipe&lt;BR&gt;場所 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure)&lt;BR&gt;場所 Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, String procedure, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src)&lt;BR&gt;場所 Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()&lt;BR&gt;場所 WindowsFormsApplication3.Form1.button1_Click(Object sender, EventArgs e) &lt;BR&gt;場所 C:\Users\ganfield\Documents\Visual Studio 2008\Projects\WindowsFormsApplication3\WindowsFormsApplication3\Form1.cs:行 58 &lt;/BLOCKQUOTE&gt;
&lt;P&gt;英語の内容だけでは何を言っているのか分かりませんｗ&lt;/P&gt;
&lt;P&gt;検証が面倒で、何故CRが許可されたりされなかったりするのか調べていません。なので、未だに原因不明。&lt;/P&gt;
&lt;P&gt;無名ブロックを書くときだけの注意点なので、上記のエラーが発生したCRを削ればいい、ぐらいに考えても良いと思います。&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;と、以上が回避策となります。これでMerge文もOracleで楽観ロック形式の同時実行制御付きで実行することができます。&lt;/P&gt;
&lt;P&gt;ま、例外があがったりするので、DBのファクトリクラスなどを使用して抽象的に処理することはできませんので、若干とほほな感じもしますが&amp;#8230;&lt;/P&gt;&lt;/A&gt;
&lt;BLOCKQUOTE&gt;&lt;/BLOCKQUOTE&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/173574.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>Merge文とExecuteNonQueryとSQLServerとOracle 時々バグ？</title><link>http://blogs.wankuma.com/ganfield/archive/2009/05/23/173492.aspx</link><pubDate>Sat, 23 May 2009 19:02:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/05/23/173492.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/173492.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/05/23/173492.aspx#Feedback</comments><slash:comments>1008</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/173492.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/173492.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://blogs.wankuma.com/ganfield/archive/2009/05/23/173465.aspx"&gt;前回のブログ&lt;/A&gt;で、やじゅさんからODP側のバグじゃないかって話があがったので、一旦動作をまとめました。今回はODP.NETだけでなく、System.Data.OracleClientも含んでいます。&lt;/P&gt;
&lt;P&gt;ちなみに、&lt;A href="http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/win.111/E05791-01/OracleCommandClass.htm#i998164"&gt;ODP.NETのマニュアル&lt;/A&gt;ではExecuteNonQueryについて、次のように述べています。&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;CODE&gt;XmlCommandType&lt;/CODE&gt;および&lt;CODE&gt;CommandText&lt;/CODE&gt;プロパティを使用してSQL文またはコマンドを実行し、影響を受ける行数を戻します&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;更新していなくても、更新していても、ExecuteNonQueryメソッドから「-1」が返ってきている時点でかなりアウトくさいです。つーかアウトですよね。影響を受けた行数が負ってどういうことじゃ！&lt;FONT color=#d3d3d3&gt;逆にこっちが影響受けた！？ｿﾝﾅﾊﾞｶﾅ&lt;/FONT&gt;&lt;/P&gt;
&lt;H4&gt;DDLとコード&lt;/H4&gt;
&lt;P&gt;1. テーブル&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ae43ed0e-b75c-43f1-989f-80a020c95b09 class=wlWriterEditableSmartContent&gt;&lt;PRE class=sql name="code"&gt;CREATE TABLE MERGETABLE
(
  KEY1 NUMBER(6,0),
  COL1 VARCHAR2(50),
  COL2 VARCHAR2(50),
  OPTLOCK TIMESTAMP(9),
  CONSTRAINT MERGETABLE_PK PRIMARY KEY (KEY1)
)&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;2. ソースコード&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:812469c5-0cb0-4c63-8c15-c81123a09de7:96ebd486-2783-401f-a826-4405a8d92a4d class=wlWriterEditableSmartContent&gt;&lt;PRE class=c# name="code"&gt;// Merge文
const string sql
= @"MERGE INTO MergeTable Target
USING (SELECT :key1 Key1, :col1 Col1, :col2 Col2, :optLock OptLock
  FROM DUAL) InputSrc
ON (Target.Key1 = InputSrc.Key1)
WHEN MATCHED THEN
  UPDATE SET
    Col1 = InputSrc.Col1
    , Col2 = InputSrc.Col2
  WHERE Target.OptLock = InputSrc.OptLock
WHEN NOT MATCHED THEN
  INSERT (Key1, Col1, Col2, OptLock)
    VALUES (InputSrc.Key1, InputSrc.Col1, InputSrc.Col2, systimestamp)
";

// Merge文実行
private int ExecuteMergeSql()
{
    using (OracleConnection conn = new OracleConnection("user id=xxx;password=yyy;data source=zzz"))
    {
        conn.Open();
        OracleCommand command = conn.CreateCommand();
        command.BindByName = true;
        command.CommandText = sql;
        command.Parameters.Add(new OracleParameter("key1", 2));
        command.Parameters.Add(new OracleParameter("col1", "aaa"));
        command.Parameters.Add(new OracleParameter("col2", "bbb"));
        command.Parameters.Add(new OracleParameter("optLock", DateTime.Now));

        int result = command.ExecuteNonQuery();
        return result;
    }
}&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;上記のソースコードはODP.NETのものです。System.Data.OracleClientを使用する場合は、BindByNameの一行をコメントアウトして下さい。&lt;/P&gt;
&lt;H4&gt;&lt;/H4&gt;
&lt;P&gt;&lt;/P&gt;
&lt;H4&gt;実行結果&lt;/H4&gt;
&lt;TABLE border=1 cellSpacing=0 cellPadding=2 width=591&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=186 align=middle&gt;クライアント&lt;/TD&gt;
&lt;TD vAlign=top width=124 align=middle&gt;サーバ&lt;/TD&gt;
&lt;TD vAlign=top width=71 align=middle&gt;結果&lt;/TD&gt;
&lt;TD vAlign=top width=208 align=middle&gt;備考&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=191&gt;System.Data.SqlClient&lt;/TD&gt;
&lt;TD vAlign=top width=128&gt;SQLServer2008&lt;/TD&gt;
&lt;TD vAlign=top width=70 align=middle&gt;○&lt;/TD&gt;
&lt;TD vAlign=top width=202&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=195&gt;System.Data.OracleClient&lt;/TD&gt;
&lt;TD vAlign=top width=131&gt;OracleXE&lt;/TD&gt;
&lt;TD vAlign=top width=68 align=middle&gt;○&lt;/TD&gt;
&lt;TD vAlign=top width=198&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=198 align=middle&gt;〃&lt;/TD&gt;
&lt;TD vAlign=top width=133&gt;Oracle11g&lt;/TD&gt;
&lt;TD vAlign=top width=68 align=middle&gt;○&lt;/TD&gt;
&lt;TD vAlign=top width=196&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=200&gt;ODP.NET(2.111.6.20)&lt;/TD&gt;
&lt;TD vAlign=top width=135&gt;OracleXE&lt;/TD&gt;
&lt;TD vAlign=top width=67 align=middle&gt;&amp;#215;&lt;/TD&gt;
&lt;TD vAlign=top width=193&gt;-1が返却される。&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top width=201 align=middle&gt;〃&lt;/TD&gt;
&lt;TD vAlign=top width=136&gt;Oracle11g&lt;/TD&gt;
&lt;TD vAlign=top width=67 align=middle&gt;&amp;#215;&lt;/TD&gt;
&lt;TD vAlign=top width=193&gt;-1が返却される。&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;なんとSystem.Data.OracleClientは正しく動いている。というか、ODP.NETの独り負けのように見える&amp;#8230;&lt;/P&gt;
&lt;P&gt;何度かMerge文の記述方法を変えたりしましたが、全てアウト。ちょっと残念だー。&lt;/P&gt;
&lt;P&gt;ほかの環境を試せたら良かったのですが、手元の環境ではこれが精一杯でした。とりあえずOracleに一報入れておきます。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/173492.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>がんふぃーるど(ganfield@wankuma.com)</dc:creator><title>Merge文とExecuteNonQueryとSQLServerとOracle</title><link>http://blogs.wankuma.com/ganfield/archive/2009/05/23/173465.aspx</link><pubDate>Sat, 23 May 2009 00:19:00 GMT</pubDate><guid>http://blogs.wankuma.com/ganfield/archive/2009/05/23/173465.aspx</guid><wfw:comment>http://blogs.wankuma.com/ganfield/comments/173465.aspx</wfw:comment><comments>http://blogs.wankuma.com/ganfield/archive/2009/05/23/173465.aspx#Feedback</comments><slash:comments>471</slash:comments><wfw:commentRss>http://blogs.wankuma.com/ganfield/comments/commentRss/173465.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/ganfield/services/trackbacks/173465.aspx</trackback:ping><description>&lt;H4&gt;Merge文って？&lt;/H4&gt;
&lt;P&gt;Merge文はSQL Serverでは2008より、Oracleでは9iぐらいから実装されたSQL構文です。&lt;/P&gt;
&lt;P&gt;機能としては、Insert OR Update（存在しなければInsert,存在すればUpdate）、もしくは、Insert OR Update OR&amp;nbsp;Delete（存在しなければInsert,存在すればUpdate OR Delete）を行ってくれます。&lt;/P&gt;
&lt;P&gt;ちなみに、SQL ServerとOracleではMerge文の構文が少し違ったりします。Merge文自体SQL2003から追加された標準なのですが、Oracleは以前から実装している関係上、下位互換が必要（Update時にWhere句を付与可能とか）ですし、SQL ServerはSQL Serverで独自の拡張（WHEN MATCHED のあとにANDコンディション付与可能とか）をしています。&lt;/P&gt;
&lt;P&gt;差異があるとはいえ、ほぼ同じような構文ですし、今回はExecuteNonQueryにおける違いを説明するので、あんまそっちのほうは詳しく述べません。&lt;/P&gt;
&lt;H4&gt;ExecuteNonQueryの何が違うの？&lt;/H4&gt;
&lt;P&gt;まずは次のSQLを用意します。&lt;/P&gt;
&lt;P&gt;1. SQL Server 2008用のMerge文&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cbfb4c10-99a3-4d21-ae73-d4a809e1623a class=wlWriterEditableSmartContent&gt;&lt;PRE class=sql name="code"&gt;MERGE INTO MergeTable as Target
USING (VALUES(@key1, @col1, @col2, @optLock))
  as InputSrc (Key1, Col1, Col2, OptLock)
ON Target.Key1 = InputSrc.Key1
WHEN MATCHED AND Target.OptLock = InputSrc.OptLock THEN
  UPDATE SET
    Col1 = InputSrc.Col1
    , Col2 = InputSrc.Col2
WHEN NOT MATCHED THEN
  INSERT (Key1, Col1, Col2)
    VALUES (InputSrc.Key1, InputSrc.Col1, InputSrc.Col2);&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;2. Oracle用のMerge文&lt;/P&gt;
&lt;DIV style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id=scid:812469c5-0cb0-4c63-8c15-c81123a09de7:8fab930c-9258-4725-bbe0-f1e84dbf0a9d class=wlWriterEditableSmartContent&gt;&lt;PRE class=sql name="code"&gt;MERGE INTO MergeTable Target
USING (SELECT :key1 Key1, :col1 Col1, :col2 Col2, :optLock OptLock
  FROM DUAL) InputSrc
ON (Target.Key1 = InputSrc.Key1)
WHEN MATCHED THEN
  UPDATE SET
    Col1 = InputSrc.Col1
    , Col2 = InputSrc.Col2
  WHERE Target.OptLock = InputSrc.OptLock
WHEN NOT MATCHED THEN
  INSERT (Key1, Col1, Col2, OptLock)
    VALUES (InputSrc.Key1, InputSrc.Col1, InputSrc.Col2, systimestamp);&lt;/PRE&gt;&lt;/DIV&gt;
&lt;P&gt;詳しくは述べませんといった舌の根も乾かぬうちに脱線してしまいますが（＾＾；）、二つのSQLの大きな違いは、SQLServer2008の5行目とOracleの9行目です。これらは楽観ロックを実装している部分です。SQL2003のBNFを確認したところ、そもそも標準にON句以外で追加の条件を指定する仕組みがなく、OracleとSQLServer2008ともに追加条件に対する部分を拡張しているとも取れます。（Oracleはそもそも9iの時代からこうだったのかもしれませんが&amp;#8230;（未確認））&lt;/P&gt;
&lt;P&gt;閑話休題&lt;/P&gt;
&lt;P&gt;さて、ExecuteNonQueryを実行した結果ですが、結論だけ言ってしまうと&amp;#8230;&lt;/P&gt;
&lt;P&gt;Oracleの場合、ExecuteNonQueryを使用して流すと、メソッドの返却値として「-1」が返ってきてしまいます！（環境は&lt;STRONG&gt;OracleXE&lt;/STRONG&gt;と&lt;STRONG&gt;ODP.NET 10.2&lt;/STRONG&gt;）&lt;/P&gt;
&lt;P&gt;一方、SQL Serverの方はといえば、ちゃんと更新した行数が返ってきます。さすがMS大先生。&lt;/P&gt;
&lt;P&gt;しかし、MSしっかりしているなぁ～などと思ってMSDNのSqlCommand.ExecuteNonQueryの項目を読んでみると&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;UPDATE、INSERT、および DELETE ステートメントでの戻り値は、そのコマンドの影響を受ける行数です。他の種類のステートメントでの戻り値は、-1 です。ロールバックが発生した場合も、戻り値は -1 です。&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;文書が更新されてませんなぁｗ&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/ganfield/aggbug/173465.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>