XPOのSQL直接実行機能 (Direct SQL Queries) を利用する場合、以下のメソッドがあります。
- ExecuteQuery
- SQLを実行して結果をSelectedDataで取得
- ExecuteQueryWithMetadata
- SQLを実行して結果をSelectedDataで取得。尚、結果とともに列情報も取得する
- ExecuteNonQuery
- 更新系クエリ発行
- GetObjectsFromQuery
- SQLを実行して、結果を指定したT型にマッピングして返す
上記のメソッドの内、ExecuteQueryWithMetadataがちょっと特殊です。
このメソッドには、ExecuteQueryと同様のパラメータを渡して実行できます。
結果も、同じSelectedDataです。ですが、このメソッドの場合は
ついでに列情報も返してくれます。
- Session.ExecuteQueryWithMetadata(String) Method
- How to: Access Data in SQL Query Results
- Table Valued Function in XPO (and XAF)?
列情報は、SelectedData.ResultSet[]の先頭に格納されています。
なので、ExecuteQueryWithMetadataを実行した場合、結果データは[1]の方に
含まれています。
var dbData = uow.ExecuteQueryWithMetadata(sql); var columnsInfo = dbData.ResultSet[0]; var queryResult = dbData.ResultSet[1];
列情報は以下のように設定されています。
foreach (var row in columnsInfo.Rows) { var columnName = row.Values[0]; // 列名 var dbColumnType = row.Values[1]; // DB側の列型名 (nvarcharとか) var columnType = row.Values[2]; // .NET側の列型名 (stringとか) }
この列情報ですが、XPDataViewを構築する場合に便利です。
通常、XPDataViewを構築する際、事前にマッピングクラスを定義していると
楽なのですがクラスも定義したくない場合、以下のようにします。
var view = new XPDataView(); view.AddProperty("Id", typeof(int)); view.AddProperty("Name", typeof(string)); view.LoadData(dbData);
上記を見ると分かるように、表示列定義を指定していっています。
これを、ExecuteWithMetadataから取得した列情報で設定すると
以下のようにできます。
var view = new XPDataView(); foreach (var row in columnsInfo.Rows) { view.AddProperty(row.Values[0] as string, DBColumn.GetType((DBColumnType) Enum.Parse(typeof(DBColumnType), row.Values[2] as string))); } view.LoadData(new SelectedData(queryResult));
XPDataViewに設定する部分に関しては、若干冗長なので、拡張メソッドにしてみました。
(Gistにアップしています: https://gist.github.com/4181320)
using DevExpress.Xpo; namespace DevExpress.Xpo { public static class XPDataViewExtensions { // // [usage] // var view = new XPDataView(); // var selectData = uow.ExecuteQueryWithMetaData(sql); // // view.FillProperties(selectData.ResultSet[0]) // .LoadData(new SelectedData(selectData.ResultSet[1]); // public static XPDataView FillProperties(this XPDataView self, SelectStatementResult schemaResult) { foreach (var row in schemaResult.Rows) { var propName = row.Values[0] as string; var propType = DBColumn.GetType((DBColumnType)Enum.Parse(typeof(DBColumnType), row.Values[2] as string)); self.AddProperty(propName, propType); } return self; } // // [usage] // new XPDataView().FillAndLoad(uow.ExecuteQueryWithMetaData(sql, names, values).ResultSet); // public static XPDataView FillAndLoad(this XPDataView self, SelectStatementResult[] results) { self.FillProperties(results[0]) .LoadData(new SelectedData(results[1])); return self; } // // [usage] // new XPDataView().FillAndLoad(sess, sql); // public static XPDataView FillAndLoad(this XPDataView self, Session sess, string sql) { return self.FillAndLoad(sess.ExecuteQueryWithMetadata(sql).ResultSet); } } }
以下、サンプルです。
(Gistにアップしています: https://gist.github.com/4181499)
namespace WpfApplication1 { using System; using System.Collections.Generic; using System.Linq; using System.Windows; using DevExpress.Xpo; using DevExpress.Xpo.DB; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new DataSource(); } } public class DataSource { public DataSource() { Setup(); } public XPDataView Data { get; private set; } private void Setup() { var connectionString = MSSqlConnectionProvider.GetConnectionString("sever", "user", "passwd", "database"); var dataLayer = XpoDefault.GetDataLayer(connectionString, AutoCreateOption.SchemaAlreadyExists); using (var uow = new UnitOfWork(dataLayer)) { var sql = "SELECT Id, Name FROM BookGenre WHERE Name = @Name"; var dbData = uow.ExecuteQueryWithMetadata(sql, new[] { "Name" }, new[] { "Computer" }); Data = new XPDataView().FillAndLoad(dbData.ResultSet); } } } public static class XPDataViewExtensions { public static XPDataView FillProperties(this XPDataView self, SelectStatementResult schemaResult) { foreach (var row in schemaResult.Rows) { var propName = row.Values[0] as string; var propType = DBColumn.GetType((DBColumnType)Enum.Parse(typeof(DBColumnType), row.Values[2] as string)); self.AddProperty(propName, propType); } return self; } public static XPDataView FillAndLoad(this XPDataView self, SelectStatementResult[] results) { self.FillProperties(results[0]) .LoadData(new SelectedData(results[1])); return self; } public static XPDataView FillAndLoad(this XPDataView self, Session sess, string sql) { return self.FillAndLoad(sess.ExecuteQueryWithMetadata(sql).ResultSet); } } }
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場