LINQ-to-SQL активно загружает весь граф объектов - PullRequest
2 голосов
/ 12 мая 2010

Мне нужно загрузить весь граф объектов LINQ-to-SQL с определенной точки вниз, загрузить все дочерние коллекции и объекты внутри них и т. Д. Это будет использоваться для выгрузки структуры объекта и данных в XML.

Есть ли способ сделать это без генерации большого жестко закодированного набора DataLoadOptions для «формирования» моих данных?

Ответы [ 3 ]

2 голосов
/ 12 мая 2010

Да, вы можете сделать это с помощью проекции a.k.a. select. Выбор LINQ to SQL позволит оптимизировать запрос и получать только то, что нужно. Есть два основных сценария. Один путешествует по реляционному дереву от многих к одному, а другой - от одного ко многим. Вот пример много к одному:

var unshippedOrders =
    from order in db.Orders
    where order.ShipDate == null
    select
    {
        OrderId = order.Id,
        CustomerId = order.Customer.Id,
        CustomerName = order.Customer.Name
    };

А вот пример от одного ко многим:

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
            }
    };

Как видите, во втором запросе у меня есть другой подзапрос, LINQ to SQL решит это за вас. В моих примерах я использовал анонимные типы, но вы также можете использовать простые старые именованные типы. Я думаю, вы даже можете смешать свой код LINQ to SQL с вашим LINQ to XML, создавая узлы XElement прямо в запросе LINQ to SQL :-). Небо это предел.

<ч />

Какого черта, приведу пример, если 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);
2 голосов
/ 12 мая 2010

Нет, я не верю, что есть.

0 голосов
/ 16 октября 2010

Если вы не хотите поддерживать эти DataLoadOptions вручную, вы можете использовать T4 Toolbox , чтобы сгенерировать ваши классы L2S и настроить генератор DataContext для создания свойства DataLoadOptions, которое вы можете назначить DataContext LoadOptions собственность, когда вам это нужно. Это то, что я сделал, и теперь, когда я хочу 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
...