2010-05-12 3 views
2

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

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

+1

Есть ли способ сделать это автоматически? Нет, не то, что я знаю. Однако я могу предложить подход, который вы, возможно, захотите попробовать. У меня нет рабочего примера этого, но он должен работать. Вы можете использовать отражение, чтобы изучить свойства вашего корневого объекта, ища свойства, которые являются EntitySets (детские коллекции). Каждый раз, когда вы его находите, вы можете использовать эту информацию для программной сборки DataLoadOptions на лету. Добавьте тире рекурсии, некоторую дублирующую проверку, и вы должны быть установлены. – Mel

+0

@Mel - интересная идея - я мог бы посмотреть на что-то подобное, но я начинаю немного настороженно относиться к (a) большому результату SQL, чтобы с нетерпением загрузить все и (б) выполнить одну медленную операцию и добавить отражая это, чтобы сделать это немного медленнее ... Вернемся к чертежной доске, я думаю. – Paddy

ответ

2

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

2

Да, вы можете сделать это, используя проекцию 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 к 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); 
+0

Хороший ответ, но по-прежнему требуется кодирование всей иерархии в проекции, которая была бы немного громоздкой (она довольно глубокая). – Paddy

+1

Я думаю, что ключевая концепция здесь заключается в том, что, предположительно, если вы хотите целый график, это потому, что у вас есть операция, которую вы намереваетесь выполнять на своих дальнейших листьях. Пока эти листья представлены в проекции, вы должны получить то, что хотите. Если у вас нет определенной цели для листьев, то зачем их извлекать в первую очередь? – Mel

0

Если вы не хотите, чтобы вручную сохранить эти 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 

 Смежные вопросы

  • Нет связанных вопросов^_^