Доступ LINQ-2-SQL DataContext в классе объекта

Во многом благодаря ответу @ anthony на подобный вопрос здесь , у меня, кажется, есть некоторый рабочий код ...

  // Prepare Article URLs list as an array
  $article_urls = array();

  // Call Airtable records in pages of 100 max
  do {

        // Offset is either inherited from last page's results, or is nothing
        $offset = $articles['offset'] ?: "";

        // Make get request, store result in array
        $articles = get_airtable_records($offset);

        // For each URL found in Airtable
        foreach($articles['records'] as $record){
           $url = $record['fields']['Published url'];
           // Add to our array list
           if (!empty($url)) {
              array_push($article_urls, $url);
           }
        }

  } while(!empty($articles['offset'])); // If there's an offset value (ie. starting record of next page), do again

  // Output URL list for check
  echo '
';
  print_r($article_urls);
  echo '
';

Объяснение выглядит следующим образом:

Используйте петлю do while. В начале этого установите offset либо значение, унаследованное от предыдущего запуска, либо ничего.

Моя get_airtable_records функция уже ограничивала присутствие или отсутствие offset в вызове API следующим образом, который добавляет строку запроса offset к URL-адресу для следующего вызова API, если таковой имеется. .

  if (!empty($offset)) {
    $q_offset = '&offset='.$offset;
  }

Я проверил это, и он дал мне все 137 результатов с двух страниц в моем массиве $article_urls. Я не тестировал его с более чем двумя страницами результатов.

9
задан Rex M 2 May 2009 в 01:58
поделиться

5 ответов

В основном, нет.

EntitySet<T> класс имеет внутреннее Source свойство, которое присвоено контекстом данных, который является, как это достигает данные, по запросу. Однако нет ничего подобного для самих классов данных.

Однако я полагаю, что Платформа Объекта имеет намного больше доступа к этому, за счет вынужденной иерархии объектов.

В отличие от Платформы Объекта, LINQ-SQL (дизайном) может использоваться с регулярными, неосведомленными персистентности классами - таким образом, это не предполагает, что имеет доступ к этому типу данных.

3
ответ дан 4 December 2019 в 21:13
поделиться

Класс Объекта не должен знать о контексте данных как его просто, отображение таблицы, но контекста данных имеет знание всех объектов и свойств соединения

Вы можете связаться с дочерней таблицей через родительский класс объекта из-за связи сущностей а не через контекст данных

Класс контекста данных будет использоваться в конце, где объекты используются, я не вижу потребность в объектах для знания о контексте,

Если можно сказать определенному сценарию, что мы можем попробовать другой подход.

1
ответ дан 4 December 2019 в 21:13
поделиться

Я точно знаю, что вы имеете в виду. Предполагается, что мы должны выполнять наши вычисления / проверку в частичном классе сущности, но если у сущности нет доступа к текстовому тексту данных, то сколько мы можем сделать? Например, в моем объекте SalesOrder всякий раз, когда адрес «Отправлять» изменяется, SalesOrder должен запросить базу данных, чтобы выяснить, применяется ли налог к ​​этому состоянию / почтовому индексу. Я боролся с этим некоторое время, но сегодня я сломался и пошел с уродливым методом, но пока все хорошо. По сути, все, что я делаю, - это создаю свойство «Context» в моем частичном классе и задаю его с помощью datacontext при создании сущности.

Partial Class SalesOrder
    Private moContext As L2S_SalesOrdersDataContext

    Friend Property Context() As L2S_SalesOrdersDataContext
        Get
            Return moContext
        End Get
        Set(ByVal value As L2S_SalesOrdersDataContext)
            moContext = value
        End Set
    End Property
...

YMMV, особенно если вы отсоединяете свои сущности.

0
ответ дан 4 December 2019 в 21:13
поделиться

В принципе, вы можете сделать это с помощью небольшого хака. DataCOntext прикрепляет StandardChangeTracker к вашей сущности:

            DataContext context = null;
            object changeTracker = (from i in o1.GetInvocationList() where i.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker" select i.Target).FirstOrDefault();
            if (changeTracker != null) // DataCOntext tracks our changes through StandardChangeTracker
            {
                object services = Reflector.GetFieldValue(changeTracker, "services");
                context = (DataContext)Reflector.GetFieldValue(services, "context");
            }

Where Reflector.GetFieldValue equals to

        public static object GetFieldValue(object instance, string propertyName)
        {
            return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
        }
0
ответ дан 4 December 2019 в 21:13
поделиться

Мне только что пришлось сделать точно то же самое. Вот мое решение (хотя, возможно, это не лучший подход, но, по крайней мере, довольно элегантный):

Во-первых, создайте интерфейс для всех ваших сущностей, который будет наследоваться от INotifyPropertyChanging. Это используется для подключения некоторых методов расширения и сохранения раздельной реализации. В моем случае интерфейс называется ISandboxObject:

public interface ISandboxObject : INotifyPropertyChanging
{
    // This is just a marker interface for Extension Methods
}

Затем создайте новый статический класс, который будет содержать метод расширения для получения DataContext. Это достигается путем поиска обработчика события на LINQ Change Tracker, прикрепленного к событию INotifyPropertyChanging.PropertyChanging. Как только мы нашли трекер изменений, мы можем получить DataContext оттуда:

    /// <summary>
    /// Obtain the DataContext providing this entity
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static DataContext GetContext(this ISandboxObject obj)
    {
        FieldInfo fEvent = obj.GetType().GetField("PropertyChanging", BindingFlags.NonPublic | BindingFlags.Instance);
        MulticastDelegate dEvent = (MulticastDelegate)fEvent.GetValue(obj);
        Delegate[] onChangingHandlers = dEvent.GetInvocationList();

        // Obtain the ChangeTracker
        foreach (Delegate handler in onChangingHandlers)
        {
            if (handler.Target.GetType().Name == "StandardChangeTracker")
            {
                // Obtain the 'services' private field of the 'tracker'
                object tracker = handler.Target;
                object services = tracker.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tracker);

                // Get the Context
                DataContext context = services.GetType().GetProperty("Context").GetValue(services, null) as DataContext;
                return context;
            }
        }

        // Not found
        throw new Exception("Error reflecting object");
    }

Теперь у вас есть хороший метод расширения, который предоставит вам DataContext из любого объекта, реализующего ISandboxObject. Пожалуйста, сделайте дополнительную проверку ошибок, прежде чем использовать его в гневе!

6
ответ дан 4 December 2019 в 21:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: