LINQ-to-SQLオブジェクトグラフ全体を特定のポイントから下にロードし、すべての子コレクションとその中のオブジェクトなどをロードする必要があります。これは、オブジェクト構造とデータをXMLにダンプするために使用されます。
データを「整形」するためにハードコードされた大量のDataLoadOptionsのセットを生成せずにこれを行う方法はありますか?
LINQ-to-SQLオブジェクトグラフ全体を特定のポイントから下にロードし、すべての子コレクションとその中のオブジェクトなどをロードする必要があります。これは、オブジェクト構造とデータをXMLにダンプするために使用されます。
データを「整形」するためにハードコードされた大量のDataLoadOptionsのセットを生成せずにこれを行う方法はありますか?
いいえ、あるとは思いません。
はい、プロジェクション別名を使用してこれを行うことができますselect
。LINQ to SQL selectを使用すると、クエリを最適化し、必要なものだけを取得できます。2つの基本的なシナリオがあります。1つはリレーショナルツリーを上に移動し、多くから1つに移動し、もう1つは下に移動して1から多に移動します。これは、多対1の例です。
var unshippedOrders =
from order in db.Orders
where order.ShipDate == null
select
{
OrderId = order.Id,
CustomerId = order.Customer.Id,
CustomerName = order.Customer.Name
};
そして、これが1つから多数までの例です。
var unshippedOrdersPerCustomer =
from customer in db.Customers
select
{
CustomerId = customer.Id,
CustomerName = customer.Name
UnshippedOrders =
from order in customer.Orders
where order.ShipDate == null
select
{
OrderId = order.Id,
OrderPrice = order.Price
}
};
ご覧のとおり、2番目のクエリには別のサブクエリがあり、LINQtoSQLがこれを解決します。私の例では匿名型を使用しましたが、単純な古い名前付き型を使用することもできます。LINQ to SQLクエリでXElementノードを作成することで、LINQtoSQLコードとLINQtoXMLを混在させることもできると思います:-)。空が限界です。
なんと、LINQ to SQL+XMLの例を挙げましょう。
XElement xml = new XElement("customers",
from customer in db.Customers
select new XElement("customer",
from order in customer.Orders
where order.ShipDate == null
select new XElement("order",
new XAttribute("id", order.Id),
new XAttribute("price", order.Price)
)
));
Console.WriteLine(xml);
これらのDataLoadOptionsを手動で保守したくない場合は、T4 Toolboxを使用してL2Sクラスを生成し、DataContextジェネレーターをカスタマイズして、必要なときにDataContextLoadOptionsプロパティに割り当てることができるDataLoadOptionsプロパティを構築できます。それが私がしたことであり、オブジェクトとそのすべての子孫をXMLシリアル化する場合は、それが可能です。
このコードをLinqToSqlDataContextTemplate.ttに追加しました
/// <summary>
/// Sets up a property that will allow loading of all child properties.
/// This is done to make serializing and entire object graph easier.
/// </summary>
private void SetupChildLoading() {
#>
private DataLoadOptions loadAllChildrenOptions;
public DataLoadOptions LoadAllChildrenOptions
{
get
{
if (loadAllChildrenOptions == null) {
loadAllChildrenOptions = new DataLoadOptions();
<#+
this.PushIndent(" ");
foreach (Table t in this.Database.Table) {
for (int i = 0; i < t.Type.Items.Length; i++)
{
Association association = t.Type.Items[i] as Association;
if (association != null)
{
if (association.AccessModifier == GeneratedTextTransformation.AccessModifier.Public && !association.IsForeignKey) {
this.WriteLine("loadAllChildrenOptions.LoadWith<{0}>(Q => Q.{1});",t.Type.Name.ToString(),association.Member);
}
}
}
}
this.PopIndent();
#>
}
return loadAllChildrenOptions;
}
}
<#+
}
そして、TransformTextメソッドでは:
#region LoadOptions
<#+ SetupChildLoading(); #>
#endregion