Доступ к DataQtext LINQ-2-SQL в классе сущностей - PullRequest
10 голосов
/ 15 декабря 2008

Есть ли простой способ доступа к DataContext в классе сущностей linq2sql.

Я пытаюсь создать что-то вроде EntitySet, но я не могу понять, как у EntitySet есть доступ к контексту, который в первую очередь создал объект сущности.

Я хочу иметь обычный класс сущностей linq2sql с возможностью доступа к классу DataContext, который его создал. Я знаю, что это возможно, потому что когда у вас есть класс сущностей с первичным ключом, linq2sql дает вам возможность загрузить все дочерние элементы без создания нового DataContext.

Ответы [ 5 ]

6 голосов
/ 12 марта 2010

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

Во-первых, создайте интерфейс для всех ваших сущностей для реализации, который наследуется от 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. Пожалуйста, добавьте еще несколько проверок на ошибки, прежде чем использовать их в гневе!

3 голосов
/ 15 декабря 2008

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

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

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

В отличие от Entity Framework, LINQ-to-SQL (по замыслу) может использоваться с обычными, невосприимчивыми к постоянству классами - поэтому он не предполагает, что имеет доступ к данным этого типа.

1 голос
/ 05 апреля 2009

Класс Entity не должен знать о контексте данных как о своем отображении таблицы, но контекст данных знает все сущности и свойства соединения

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

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

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

0 голосов
/ 11 февраля 2010

В принципе, вы можете сделать это с небольшим количеством взлома. 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");
            }

Где Reflector.GetFieldValue равно

        public static object GetFieldValue(object instance, string propertyName)
        {
            return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
        }
0 голосов
/ 04 мая 2009

Я точно знаю, что вы имеете в виду. Предполагается, что мы должны выполнять наши вычисления / проверку в частичном классе сущности, но если у сущности нет доступа к текстовому тексту данных, то сколько мы можем сделать? Например, в моем объекте 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, особенно если вы отделяете свои сущности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...