Подтвердить что ты не робот

LinqToSql объявляет и внедряет лучшую практику DataContext?

Какая наилучшая практика в плане настройки моего DataContext для легкого доступа в моих расширенных классах LinqToSql?

Например, у меня есть объект "Пользователь" в моем dbml, и я хочу добавить методы к этому классу следующим образом:

Partial Public Class User

    Public Function GetUser(ByVal UserID as Integer) as User
         'Do Work
    End Function

End Class

Чтобы получить доступ к моему DataContext, я должен был бы объявить его внутри метода следующим образом:

Partial Public Class User

    Public Function GetUser(ByVal UserID as Integer) as User
         Dim dc as New MyDataContext()
         Return (From u in dc.Users Where u.ID = UserID).Single()
    End Function

End Class

Я бы не хотел этого делать для каждого метода. Обычно (если я не расширил классы dbml LinqToSql), я мог бы просто сделать это:

Partial Public Class User
    Private dc as MyDataContext

    Public Sub New()
         dc = new MyDataContext()
    End Sub

    Public Function GetUser(ByVal UserID as Integer) as User
         Return (From u in dc.Users Where u.ID = UserID).Single()
    End Function

    Public Function GetAllUsers() as IEnumerable(Of User)
         Return From u in dc.Users
    End Function

    'etc...

End Class

Это позволит мне получить доступ к datacontext для каждого метода без необходимости объявлять его каждый раз. Но, конечно, вы не можете этого сделать, потому что у dbml уже есть конструктор. И добавление кода в dbml всегда перезаписывается, если что-либо изменится.

У кого-нибудь есть хорошие идеи о том, как сохранить здесь лишний код?

ТИА!

4b9b3361

Ответ 1

Во-первых, убедитесь, что вы удаляете свой DataContext, когда закончите! Он может быть тяжелым маленьким ублюдком ( редактировать не тяжелым, чтобы создать экземпляр, но тяжело держать, если вы продолжаете использовать его без утилизации); вы не хотите, чтобы старые DataContexts висели в памяти.

Во-вторых, DataContext предназначен для представления единой логической транзакции. Например. вы должны создавать новый каждый раз, когда хотите начать новую транзакцию, и избавиться от нее, когда эта транзакция будет завершена. Таким образом, для ваших целей это, вероятно, область применения метода GetUser. Если у вас есть серия вызовов БД, которые должны быть сделаны как группа, все они должны использовать один и тот же DC, прежде чем избавиться от него.

Ответ 2

Как Rex M сказал, datacontext предназначен для создания, использования и использования для каждой логической транзакции. Подобные шаблоны иногда называют "единицей работы".

Самый распространенный способ (который я знаю) сделать это - создать экземпляр вашего datacontext в используемом блоке. Я не использовал VB через некоторое время, но он должен выглядеть примерно так:

Using dc As New MyDataContext()
   user = (From u in dc.Users Where u.ID = UserID).Single()
End Using

Это не только упрощает внешний вид транзакции/единицы работы (через физическую форму кода), но и обеспечивает вызов Dispose() в вашем datacontext, когда заканчивается блок.

Смотрите эту страницу MSDN:

В общем случае экземпляр DataContext предназначен для того, чтобы продлиться один "блок работать", однако ваша заявка определяет этот термин. DataContext - это легкий и не дорогой Создайте. Типичный LINQ to SQL приложение создает DataContext экземпляров в области метода или в виде член недолговечных классов, которые представляют собой логический набор связанных операции с базой данных.

Ответ 3

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

Ответ 4

Есть несколько разных способов, которыми вы могли бы заняться этим, что, я думаю, будет хорошей практикой. Сначала вы можете использовать шаблон репозитория, в котором вы запрашиваете репозиторий для объекта, он выходит в базу данных, извлекает объект - возможно, отделяя его от контекста данных или сохраняя контекст данных в зависимости от реализации Репозитория - и возвращает его вам. Методы factory для ваших объектов будут находиться в репозитории, а не сами сущности. Вероятно, вы используете рефлексию и генерические средства, чтобы свести к минимуму количество методов, которые вы должны реализовать, и сохраните свой код DRY.

Другой способ и способ, которым LINQtoSQL должен был использоваться изначально IMHO, заключается в создании контекста данных для каждого набора операций с базой данных, которые вы собираетесь выполнять. В этом случае создание контекста данных происходит вне объекта, как правило, в классе, который использует сущности, а не в слое данных вообще. Вы также можете добавить методы в контекст данных - сделать ваш фактический контекст данных абстрактным и наследовать от него - снова использовать отражение, выполнить некоторые из обычных функций поиска, чтобы вам не пришлось их повторять. Вероятно, вам придется использовать шаблон базы данных, такой как ActiveRecords, где столбцы id всегда имеют одно и то же имя, чтобы сделать эту работу.

С другой стороны, вы можете посмотреть nHibernate или Замок ActiveRecord вместо того, чтобы повторять одно из указанных выше в вашем собственном решении.

Ответ 5

Это может быть проще, если вы оставите класс User в покое и позволите IDE обрабатывать его создание.

Часто я предпочитаю иметь отдельный класс для обработки данных. Допустим, вы называете его UserDataProvider, и все вызовы для получения экземпляра User в конечном итоге проходят через этот класс.

Конструктор UserDataProvider может создать глобальный экземпляр объекта контекста данных для повторного использования. Это будет выглядеть примерно так (в С# и непроверенном коде, так что терпите меня):

public class UserDataProvider 
{
    private UserDataContext _data = null;

    public UserDataProvider()
    {
        _data = new UserDataContext();
    }

    public User GetUser(int userID)
    {
        return _data.Users.FirstOrDefault(u => u.UserID == userID);
    }
}

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

public class UserDataProvider 
{
    private UserDataContext _dataContext;

    private UserDataContext DataContext 
    {
        get
        {
            if (_data == null)
                _data = new UserDataContext();

            return _data;
        }
    }

    public User GetUser(int userID)
    {
        return DataContext.Users.FirstOrDefault(u => u.UserID == userID);
    }
}