linq2sql: синглтон или использование, лучшие практики - PullRequest
7 голосов
/ 15 апреля 2010

что является предпочтительной практикой при использовании linq2sql (в приложениях asp.net mvc): для создания "singleton" для DataContext, например:

partial class db
{
    static db _db = new db(global::data.Properties.Settings.Default.nanocrmConnectionString, new AttributeMappingSource());

    public static db GetInstance()
    {
        return _db;
    }
}

или для извлечения нового экземпляра, когда это необходимо, в пределах using:

using (db _db = new db())
{
    ...
}

использование using вносит некоторые ограничения в код. поэтому я предпочитаю использовать синглтон. это странная практика?

UPD
объяснение, почему я использую синглтон:

public class UserGroupRepository
{
    public static IQueryable<Group> RolesFor(string username)
    {
        User user = UserRepository.WithUsername(username);

        return from g in db.GetInstance().Groups
                join ug in db.GetInstance().UsersGroups on g.Id equals ug.GroupId
                where ug.UserId == user.Id
                select g;
    }
}

У меня есть этот метод. из-за этого возвращает IQueryable - я могу продолжить составление запроса без его выполнения, поэтому здесь просто ленивый результат возвращает.
если я переписываю тот же код с using - я не смогу вернуть IQueryable (потому что будет удалена БД и IQueryable также будет потерян), и я бы изменил его на Список. и теперь этот метод будет возвращать «огромный» список, из которого я буду фильтровать данные предыдущей функции.

Надеюсь, я опишу достаточно подробно.

Ответы [ 3 ]

5 голосов
/ 15 апреля 2010

Контексты данных Linq to Sql НЕ являются поточно-ориентированными и должны использоваться только в контексте одного потока. Использование шаблона синглтона не только противоречит стандартным методам linq2sql, но и приведет к серьезным проблемам, если ваше приложение будет подвергаться какой-либо серьезной нагрузке.

EDIT:

В ответ на ваши ограничения в отношении использования блока, попробуйте реализовать свой метод RolesFor в качестве метода расширения:

public static IQueryable<Group> GetUserRoles(this Database db, string username)
{
        return from g in db.GetInstance().Groups
                join ug in db.GetInstance().UsersGroups on g.Id equals ug.GroupId
                where ug.UserId == user.Id
                select g;
}

Это позволит вам вызывать ваш метод внутри блока using из любого места:

using(Database db = createContext())
{
     IQueryable<Group> queryable = db.GetUserRoles("MyUsername");
     // from here on you can query the queryable object
     var groups = (from g in queryable
                   where g.Name == "MyRole"
                   select g).ToList();
}

РЕДАКТИРОВАТЬ 2

В ответ на ваш комментарий об открытии другого соединения с сервером sql для каждого экземпляра контекста данных. Создание текстового контекста не откроет соединение с сервером sql, но каждая фактическая операция будет открыта. Независимо от того, создаете ли вы 1 или 4 контекста данных, если вы выполняете 4 операции с базой данных, будет открыто 4 sqlconnections. Однако имейте в виду, что .NET использует пул соединений с сервером sql, поэтому каждая операция не требует создания полностью нового SqlConnection, а только извлечения существующего из пула соединений и повторного открытия соединения

2 голосов
/ 15 апреля 2010

Linq to SQL хочет, чтобы вы создали контекст для каждой операции. Фактически, параметры загрузки данных могут быть установлены только для выполнения первого запроса, поэтому, если вы хотите выполнить подсказки по загрузке, вы должны сделать это таким образом. Однако, если у вас 3-уровневая архитектура, вы столкнетесь с проблемой, заключающейся в том, что объекты из одного текста данных не могут работать с объектами из другого контекста.

Обойти это - настоящая боль, поэтому мы просто делали контекст для каждого запроса веб-материалов и локального подхода к потокам для служб Windows и т. П.

0 голосов
/ 15 апреля 2010

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

Поиск в Google по запросу "objectcontext в веб-области" или "время существования контекста объекта" (или datacontext для l2s).

например. http://dotnetslackers.com/articles/ado_net/Managing-Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx

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

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