Здравствуйте, IT, Вы писали:
MC>>Тут выпадает исключение "'c.ID' cannot be converted to SQL." IT>Это скорее всего бага.
Бага будет пофикшена? Не забудется?
IT>Да, точно. Строка будет рассмотрена как значение и заключена в кавычки. Тогда только наследование от SqlExpressionAttribute с перекрытием метода GetExpression.
О>Вот например с базой Northwind. Есть там такие таблицы для связи many-to-many: "Employees" <- "EmployeeTerritories" -> "Territories".
Разбираюсь со связью многие-ко-многим, в Unit тестах есть указанные выше таблицы. Но как с ними работать нет ни одного рабочего примера. Получается вытягивать данные только для агрегированых таблиц (Count и т.п.)
в небольшом примере не могли бы показать, как Вы поддерживаете такую связь
О>Скажем в Entity Framework и в NHibernate есть нативная поддержка таких ассоциаций. Для них соответсвующие классы будут выглядеть как-то так (шаблонно): О>[c#] О>public class Employee О>{ О> public int EmployeeID; О> public List<Territory> Territories; О>}
Здравствуйте, Зайцев Андрей, Вы писали: ЗА>Только начинаю пользоваться BLT, и уже сразу с Linq . Увидел, что после выполнения Linq запроса подключение к БД остаётся открытым. Вопрос: можно ли как-то настроить MyDbManager так, чтобы он закрывал подключение автоматически, без вызова Dispose, а по завершении запроса?
Немного поздновато, но все же: думаю это не MyDbManager оставляет а Connection Pool. Соответственно "pooling=false" в connection string. Но будет существенно меньше скорость (в общем случае)
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Re: Linq with BLToolkit
От:
Аноним
Дата:
02.08.10 16:36
Оценка:
Здравствуйте!
BLToolkit — просто чудо какое-то. Мы с коллегами в данный момент переводим один из проектов с L2S на BLT, модифицировали dblinq для генерации модели совместимой с BLT, все работает просто отлично. Однако остаются не ясными два момента:
1. Как правильно закрывать соединения с базой данных? Вариант с постоянным использованием using немного смущает тем, что это можно элементарно забыть сделать. Можно ли как-то с этим разобраться без ущерба производительности? (Например как в L2S)
2. Как лучше всего заполнить модель из базы данных с заполненными связанными сущностями. Из примера в статье мы видим только вариант в котором нужно перечислить все необходимые поля, включая те что не имеют ассоциации. Возможно ли указать необходимые сущности для маппинга и получить заполненный объект на подобии L2S LoadWith ?
Здравствуйте, Аноним, Вы писали:
А>1. Как правильно закрывать соединения с базой данных? Вариант с постоянным использованием using немного смущает тем, что это можно элементарно забыть сделать. Можно ли как-то с этим разобраться без ущерба производительности? (Например как в L2S)
Можно вообще не указывать контекст, тогда будет использоваться дефолтный и его время жизни будет контролироваться самой библиотекой.
ЗЫ. А как сделано в L2S?
А>2. Как лучше всего заполнить модель из базы данных с заполненными связанными сущностями. Из примера в статье мы видим только вариант в котором нужно перечислить все необходимые поля, включая те что не имеют ассоциации. Возможно ли указать необходимые сущности для маппинга и получить заполненный объект на подобии L2S LoadWith ?
В планах сразу после Linq over WCF.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Linq with BLToolkit
От:
Аноним
Дата:
02.08.10 17:49
Оценка:
Здравствуйте, IT, Вы писали:
IT>ЗЫ. А как сделано в L2S?
Я не знаю как сделано в L2S, однако после замены его провайдера на BLT и запуска ApacheBenchmark с 100 конкурентными запросами, база данных почти сразу выдала "too many connections". Когда обрамили контекст using все стало работать как надо. На сколько я понимаю дело в нашем контексте который генерируется dblinq. Возможно стоит попробовать добавить к нему деструктор...
Здравствуйте, Аноним, Вы писали:
А>Я не знаю как сделано в L2S, однако после замены его провайдера на BLT и запуска ApacheBenchmark с 100 конкурентными запросами, база данных почти сразу выдала "too many connections". Когда обрамили контекст using все стало работать как надо. На сколько я понимаю дело в нашем контексте который генерируется dblinq. Возможно стоит попробовать добавить к нему деструктор...
Деструктор поможет, но не сильно.
В принципе, на сегодняшний день, DataContext является интерфейсом и полностью отчуждаем. При желании можно написать DataContext на свой вкус и цвет.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>В принципе, на сегодняшний день, DataContext является интерфейсом и полностью отчуждаем. При желании можно написать DataContext на свой вкус и цвет.
Наверное, я не правильно выразился. Наш DataContext напрямую наследуется от DbManager и в нем просто реализуются свойства, которые вызывают DbManager.GetTable<T>.
Мы реализовали схему, при которой не требуется явное освобождение ресурсов.
Базовый репозиторий:
public class Repository<T> where T : DbManager, new()
{
public T Context {
get { return DataContext.Value; }
}
[ThreadStatic]
private volatile static Lazy<T> dataContext;
public static Lazy<T> DataContext {
get { return dataContext ?? (dataContext = new Lazy<T>( () => new T())); }
set { dataContext = value; }
}
}
Реализация репозитория: (OlympDataContext — наш domain класс, который генерируется dblinq из БД, наследует DbManager)
public class NewsRepository : Repository<OlympDataContext>
{
public List<News> GetAllNews()
{
return Context.News.ToList();
}
}
Освобождение DbManager происходит в Global.asax.cs
protected void Application_EndRequest(object sender, EventArgs e)
{
var lazy = Repository<OlympDataContext>.DataContext;
if (lazy.IsValueCreated)
{
lazy.Value.Dispose();
Repository<OlympDataContext>.DataContext = null;
}
}
Таким образом мы имеем один DbManager на все запросы для каждой страницы. Можно создавать любое количество репозиториев в контроллерах. Не нужно беспокоиться о освобождении ресурсов.
Эта схема работает. Имеем ~250 страниц в секунду на средней клиентской машине при 5 запросах к mysql.
Это вторая реализация. Первая инициализировалась следующим образом:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var lazy = new Lazy<OlympDataContext>(() => new OlympDataContext());
Repository<OlympDataContext>.DataContext = lazy;
}
Схема работала до того момента как мы начали использовать in-proc сессию. Как только мы добавили кэширование в сессии, начались случайные выпады в DbManager NullReferenceException при обращении к DbManager._connection. Стоит заметить, что из-за использования сессии производительность падает до 120 запросов в сек (независимо от схемы).
Здравствуйте, Erty Hackward, Вы писали:
IT>>В принципе, на сегодняшний день, DataContext является интерфейсом и полностью отчуждаем. При желании можно написать DataContext на свой вкус и цвет. EH>Наверное, я не правильно выразился. Наш DataContext напрямую наследуется от DbManager и в нем просто реализуются свойства, которые вызывают DbManager.GetTable<T>.
DBManager — это обёртка над соединением. Соответственно и работать с ним нужно подобным же образом, т.е. как с соединением. То, что DBManager реализует IDataContext — это лишь вопрос удобства. Вам нужен контекст, который будет сам создавать и освобождать соединение, когда нужно. Сейчас попробую, что-нибудь изобразить.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Erty Hackward, Вы писали:
IT>>В принципе, на сегодняшний день, DataContext является интерфейсом и полностью отчуждаем. При желании можно написать DataContext на свой вкус и цвет. EH>Наверное, я не правильно выразился. Наш DataContext напрямую наследуется от DbManager и в нем просто реализуются свойства, которые вызывают DbManager.GetTable<T>.
Здесь пример использования класса DataContext. Думаю, на время запроса вам нужно взводить флаг KeepConnectionAlive в true, а потом сбрасывать в false. Сам объект обнулять не надо, т.к. дальше он будет открывать/закрывать соединение автоматически.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, pr0ff, Вы писали:
P>Хм, а зачем двойная ленивая инициализация?
Первый уровень нужен для создания второго, потому что мы используем ThreadStatic и нельзя использовать конструкторы. Второй позволяет не создавать DbManager при освобождении ресурсов, если страница без запросов.
ИМХО правильней было бы контекст хранить в HttpContext.Current.Items. Это и логичней и асинхронные обработчики не будут глючить (в них выполнение обычно завершается в другом потоке)
Здравствуйте, pr0ff, Вы писали:
P>ИМХО правильней было бы контекст хранить в HttpContext.Current.Items. Это и логичней и асинхронные обработчики не будут глючить (в них выполнение обычно завершается в другом потоке)
Мы отказались от этой идеи, поскольку это потребовало бы передачи контекста в конструктор репозитория.
как нам кажется гораздо элегантнее:
var newsRepo = new NewsRepository();
Re[5]: Linq with BLToolkit
От:
Аноним
Дата:
10.10.10 21:44
Оценка:
Здравствуйте, IT, Вы писали:
IT>А если описание промежуточных сущностей всё же требовать, но иметь возможность обходится без них в запросе?
а можно увидеть, как обойтись без них в запросе? хотя бы на примерe "Employees" <- "EmployeeTerritories" -> "Territories".
Здравствуйте, Аноним, Вы писали:
IT>>А если описание промежуточных сущностей всё же требовать, но иметь возможность обходится без них в запросе? А>а можно увидеть, как обойтись без них в запросе? хотя бы на примерe "Employees" <- "EmployeeTerritories" -> "Territories".
SQL в обмен на Linq запрос.
Если нам не помогут, то мы тоже никого не пощадим.
Я правильно понял, что ассоциации используются в linq запросах как упрощение и укорачивание запроса вместо join'ов?
Есть ли возможность, получая некий объект, получить заполненнное ассоциированное свойство без выполнения ручных махинаций? Иначе говоря, для схемы в демо проекте, получая объекты Employee, получить для них заполненное свойство EmployeeTerritories.
Здравствуйте, Vlako, Вы писали:
V>Я правильно понял, что ассоциации используются в linq запросах как упрощение и укорачивание запроса вместо join'ов?
Правильно.
V>Есть ли возможность, получая некий объект, получить заполненнное ассоциированное свойство без выполнения ручных махинаций? Иначе говоря, для схемы в демо проекте, получая объекты Employee, получить для них заполненное свойство EmployeeTerritories.
В планах есть. Когда будет реализовано
Если нам не помогут, то мы тоже никого не пощадим.