Здравствуйте, _FRED_, Вы писали:
_FR>Да, для обмена лучше использовать одно представление, для показа — другое, а для рассчётов — третье Остаётся их только подружить и не запутаться во взаимоотношениях.
Три представления — три раза кодить. Не слишком ли накладно?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[6]: Buisness Entities в Распределенных приложениях
Здравствуйте, IT, Вы писали:
IT>>>Т.е. сначала закачиваешь данные в датасет, а потом переливаешь их в бизнес-объекты? _FR>>Да. Закачиваю данные в датасет, потом, где надо (наличие логики на клиенте и некоторые расчёты удобнее вести со своими сущностями, хранящими в себе разные результаты вычислений, имеющие особые арифметические операции) получаю сущности из таблицы или другого набора строк. _По месту_, то есть не храню сущности постоянно, это у меня недолгоживущие объекты. IT>А датасеты хранишь постоянно?
Да, постоянно. Подгружаю таблицы "по требованию".
IT>>>Что именно ты собираешься генерировать? _FR>>Классы сущностей. Их должно быть несколько десятков, код у них на 60% одинаков (геттеры-сеттеры свойств, закрузка\сохранение) за небольшими исключениями (типы\имена полей). Каждый класс — partial, то есть каждый можно расширить в зависимости от смысла. IT>Всё это давно умеет RFD.
Когда, примерно с год назад, я его смотрел, не понравилась идея реализовывать всё через открытые члены класса (сущности через интерфейсы объявлялись), мне же хочется гибкой связи полей БД на поля объекта, которые более естественны, например в базе целочисленная маска, а в объекте — несколько логических флагов, и чтоб о маске "снаружи" никто не догадался. Или представлять целочисленное же поле БД как ТаймСпан в объекте. И ещё было желание на полную использовать второй фрейворк
Сейчас, смотрю, он не только расширился, но и List<T> учится обрабатывать
<< RSDN@Home 1.1.4 beta 7 rev. 496 >> =04:36= [Windows XP — 5.1.2600.0] {Build at .NET 1.1.4322.2032}
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, IT, Вы писали:
_FR>>Да, для обмена лучше использовать одно представление, для показа — другое, а для рассчётов — третье Остаётся их только подружить и не запутаться во взаимоотношениях. IT>Три представления — три раза кодить. Не слишком ли накладно?
Реально-то может всё быть реализовано едино, но иметь возможность работы на три фронта. Начал я делать универсально... накладнее получилось
<< RSDN@Home 1.1.4 beta 7 rev. 496 >> =04:47= [Windows XP — 5.1.2600.0] {Build at .NET 1.1.4322.2032}
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Re[7]: Buisness Entities в Распределенных приложениях
Не нравится мне такая идея. Пару раз примерял к себе, но что-то не пошло.
_FR>Когда, примерно с год назад, я его смотрел, не понравилась идея реализовывать всё через открытые члены класса (сущности через интерфейсы объявлялись),
Такого требования в RFD нет.
_FR> мне же хочется гибкой связи полей БД на поля объекта, которые более естественны, например в базе целочисленная маска, а в объекте — несколько логических флагов, и чтоб о маске "снаружи" никто не догадался.
На энумераторы можно мапить целочисленные константы, можно строковые.
public enum Status
{
[MapValue("A")] Active,
[MapValue("I")] Inactive,
[MapValue("P")] Pending
}
_FR>Или представлять целочисленное же поле БД как ТаймСпан в объекте.
Этого нет. Но добавить это в библиотеку не проблема, тем более что случай не такой уж редкий. Сейчас можно выкрутиться примерно так:
[MapField("Time")]
protected abstract long timeInternal { get; set; }
[MapIgnore]
public TimeSpan Time
{
get { return timeInternal == 0? TimeSpan.MinValue: new TimeSpan(timeInternal); }
set { timeInternal = value == TimeSpan.MinValue? 0: value.Ticks; }
}
_FR>И ещё было желание на полную использовать второй фрейворк _FR>Сейчас, смотрю, он не только расширился, но и List<T> учится обрабатывать
Ага, пытается. Но чтобы использовать на полную нужно переписывать все внутренности. Но тогда прощай совместимость с 1-м фреймворком.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Buisness Entities в Распределенных приложениях
Здравствуйте, IT, Вы писали:
IT>>>А датасеты хранишь постоянно? _FR>>Да, постоянно. Подгружаю таблицы "по требованию".
IT>Не нравится мне такая идея. Пару раз примерял к себе, но что-то не пошло.
Мне тоже, но остановился, по причине того что пользователю придётся одновременно оперировать сразу с несколькими таблицами — тягать из одной в другую, во вьюхах отображать вместо идентификатора парент записи — поле из парент таблицы, при редактировании из комбобокса выбирать связанную запись — всё равно всю таблицу надо грузить Если таблица из сотни записей и их пять — шесть и подгружать каждый раз, то подтормаживать так же будет каждый раз. Второй бонус —
_FR>>Когда, примерно с год назад, я его смотрел, не понравилась идея реализовывать всё через открытые члены класса (сущности через интерфейсы объявлялись),
IT>Такого требования в RFD нет.
То есть можно настроить так, чтобы поля мапились на закрытые\защищённые члены класса? Ага, вижу ниже пример с протектед
_FR>> мне же хочется гибкой связи полей БД на поля объекта, которые более естественны, например в базе целочисленная маска, а в объекте — несколько логических флагов, и чтоб о маске "снаружи" никто не догадался.
IT>На энумераторы можно мапить целочисленные константы, можно строковые.
С енумами ясно, но в базе могут храниться маски, биты которых друг к другу отношения не имеют, например "Просмотрено", "Отредактировано", "Помечено" и более естественным для них, имхо, иметь именно булевские переменные.
_FR>>Или представлять целочисленное же поле БД как ТаймСпан в объекте. IT>Этого нет. Но добавить это в библиотеку не проблема, тем более что случай не такой уж редкий. Сейчас можно выкрутиться примерно так:
IT>[MapField("Time")]
IT>protected abstract long timeInternal { get; set; }
IT>[MapIgnore]
IT>public TimeSpan Time
IT>{
IT> get { return timeInternal == 0? TimeSpan.MinValue: new TimeSpan(timeInternal); }
IT> set { timeInternal = value == TimeSpan.MinValue? 0: value.Ticks; }
IT>}
Да, примерно это и надо. Нормально ли Rfd отнесётся к тому, что из сеттера "public TimeSpan Time" я брошу исключение. мол "неверное значение"? В смысле получу ли я его (через InnerException конечно) в вызывающей стороне?
_FR>>И ещё было желание на полную использовать второй фрейворк _FR>>Сейчас, смотрю, он не только расширился, но и List<T> учится обрабатывать
IT>Ага, пытается. Но чтобы использовать на полную нужно переписывать все внутренности. Но тогда прощай совместимость с 1-м фреймворком.
Ну почему же "прощай совместимость". Ради широты охвата можно и продублировать кой-какие куски, зато все будут довольны
<< RSDN@Home 1.1.4 beta 7 rev. 496 >> =06:38= [Windows XP — 5.1.2600.0] {Build at .NET 1.1.4322.2032}
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Buisness Entities в Распределенных приложениях
Здравствуйте, _FRED_, Вы писали:
IT>>Не нравится мне такая идея. Пару раз примерял к себе, но что-то не пошло.
_FR>Мне тоже, но остановился, по причине того что пользователю придётся одновременно оперировать сразу с несколькими таблицами — тягать из одной в другую, во вьюхах отображать вместо идентификатора парент записи — поле из парент таблицы, при редактировании из комбобокса выбирать связанную запись — всё равно всю таблицу надо грузить Если таблица из сотни записей и их пять — шесть и подгружать каждый раз, то подтормаживать так же будет каждый раз. Второй бонус —
Значит продолжим, отвлёкся я
Второй бонус в возможности отмены\возврата операций над иерархией записей — хоть всё дерево пользовательнигде и не видит, но оно у меня есть и при необходимости я могу что-то пересчитать, что-то удалить, что-то вернуть. Опять же, имея всё это сразу, получается быстрее, чем запрашивать каждый раз.
<< RSDN@Home 1.1.4 beta 7 rev. 496 >> =06:50= [Windows XP — 5.1.2600.0] {Build at .NET 1.1.4322.2032}
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Buisness Entities в Распределенных приложениях
Здравствуйте, _FRED_, Вы писали:
_FR>То есть можно настроить так, чтобы поля мапились на закрытые\защищённые члены класса? Ага, вижу ниже пример с протектед
Это поддерживается только для абстрактных классов.
IT>>На энумераторы можно мапить целочисленные константы, можно строковые.
_FR>С енумами ясно, но в базе могут храниться маски, биты которых друг к другу отношения не имеют, например "Просмотрено", "Отредактировано", "Помечено" и более естественным для них, имхо, иметь именно булевские переменные.
Можно напрямую без всяких атрибутов мапить на энумераторы, но понятное дело что маска в базе и значения энумераторов должны совпадать. Хотя я не считаю данный подход правильным. Я для этого использую отдельные битовые поля.
_FR>Да, примерно это и надо. Нормально ли Rfd отнесётся к тому, что из сеттера "public TimeSpan Time" я брошу исключение. мол "неверное значение"? В смысле получу ли я его (через InnerException конечно) в вызывающей стороне?
Нормально.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>- отсутвие поддержки перечислителей, соответственно абстракция от структуры данных тоже идёт лесом. Использование захаркоженных значений расползается по системе, в результате чего их потом приходится ловить и давить как тараканов.
Что такое перечислители и захаркоженные значения? Как я понял, захаркоженные значения — это что-то типа
TableX.Fields["Age"].GetValue();
А есть способы избежать этого? Эти самые загадочные перечислители?
IT>Бизнес объекты как правило лишены перечисленных недостатков, но очень часто и достоинств Большинство вещей приходится делать ручками, в частности больше всего напрягает вычитывание записей из рекордсета и маппинг. Если решить эти проблемы, то всё совсем не так уж плохо
А это что-за звери? Поиск бизнес объектов в списке что-ли?
PS
В проектировании я вообще-то чайник, но кошмар с табличками/датасетами уже достал. Присматриваюсь к бизнес-объектам, но пугает большой (ИМХО) объём рутинной работы.
Здравствуйте, Mazay, Вы писали:
IT>>- отсутвие поддержки перечислителей, соответственно абстракция от структуры данных тоже идёт лесом. Использование захаркоженных значений расползается по системе, в результате чего их потом приходится ловить и давить как тараканов. M>Что такое перечислители и захаркоженные значения?
Есть таблица:
CREATE TABLE Users (
UserID int IDENTITY(1,1) NOT NULL,
---------------------------------------------
UserName nvarchar(255) NOT NULL,
UserPassword nvarchar(255) NOT NULL,
---------------------------------------------
UserKind tinyint NOT NULL, -- 1: Admin, 2: User, 3: Reader
---------------------------------------------CONSTRAINT PK_Users PRIMARY KEY CLUSTERED (UserID),
CONSTRAINT UK_Users UNIQUE (UserName),
CONSTRAINT CK_Users CHECK(len(UserName) > 1)
)
GO
Поле UserKind которой может принимать одно из следующих значений:
public enum UserKind : byte { // Это и есть перечислитель (byte - это tinyint в MSSQL)
Admin = 1,
User,
Reader,
}
Если механизм загрузки объектов из БД может их загрузить лишь в такой класс:
public class User
{
public int ID;
public string Name;
public string Password;
publicbyte Kind;
}
То экземплярам класса User придётся в поле Kind проставлять "захаркоженные значения":
User user = new DatabaseManager.GetUser(1);
user.Kind = 2; // - вот это "захаркоженное значение"
// Тут конечно можно и user.Kind = (bype)UserKind.User;, но некрасиво, да и на элемент управления такое поле просто не забиндить
DatabaseManager.UpdateUser(user);
Более грамотный DatabaseManager сможет вернуть такой класс:
public class User
{
public int ID;
public string Name;
public string Password;
publicUserKind Kind;
}
Проведя преобразование tiniint->UserKind у себя внутри. И тогда всё красивее:
User user = new DatabaseManager.GetUser(1);
user.Kind = UserKind.User;
DatabaseManager.UpdateUser(user);
M>Как я понял, захаркоженные значения — это что-то типа
M>TableX.Fields["Age"].GetValue();
M>А есть способы избежать этого? Эти самые загадочные перечислители?
Да, объявляя "Age" как константу, как-то так, например:
public static class DatabaseFields
{
public static class TableX
{
public const string Age = "Age";
}
}
// ...
// Использование
TableX.Fields[DatabaseFields.TableX.Age].GetValue();
Но, что-то я такого пока не видел.
IT>>Бизнес объекты как правило лишены перечисленных недостатков, но очень часто и достоинств Большинство вещей приходится делать ручками, в частности больше всего напрягает вычитывание записей из рекордсета и маппинг. Если решить эти проблемы, то всё совсем не так уж плохо M>А это что-за звери? Поиск бизнес объектов в списке что-ли?
Маппинг — вычитывание данных из рекордсета и простановка значений полей строки полям экземпляра класса. Посмотреть пример можно здесь
.
M>PS M>В проектировании я вообще-то чайник, но кошмар с табличками/датасетами уже достал. Присматриваюсь к бизнес-объектам, но пугает большой (ИМХО) объём рутинной работы.
Смотри RFD (Rsdn.Framework.Data) — процентов 50 а то и много больше, в простых случаях, уже сделали и отладили.
<< RSDN@Home 1.1.4 beta 7 rev. 496 >> =04:22= [Windows XP — 5.1.2600.0] {Build at .NET 1.1.4322.2032}
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Re[6]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, IT, Вы писали:
IT>Хорошее решение должно порождать простой прикладной код. Поэтому можно всегда сравнить два подхода просто написав на них одну и ту же задачу. Где прикладной код будет проще — то решение лучше. Если рассматривать датасеты vs бизнес-объекты в рамках стандартных средств, то проигрывая бизнес-объектам в простоте написания бизнес логики, датасеты вырываются далеко вперёд в том что касается чтения данных из БД и баиндинга этих данных на формы. Если решить эти две проблемы, датасеты однозначно проигрывают бизнес-объектам.
Решить эти проблемы легко. Их и за проблемы то считать не стоит, неделя работы для простейших случаев. Проблема — DataView. Повторить его функциональность уже значительно сложней.
С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[7]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, GlebZ, Вы писали:
GZ>Решить эти проблемы легко. Их и за проблемы то считать не стоит, неделя работы для простейших случаев. Проблема — DataView. Повторить его функциональность уже значительно сложней.
Думаю что для этого даже недели не понадобится. Особенно на 2-м фреймворке. На работе у меня его нет, приеду домой попробую изобразить кое что.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[8]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, IT, Вы писали:
IT>Думаю что для этого даже недели не понадобится. Особенно на 2-м фреймворке. На работе у меня его нет, приеду домой попробую изобразить кое что.
Сортировка, в принципе легко. А вот фильтрация — уже значительно сложней. Учитывая что там есть язык описания фильтров. Для 2.0 конечно можно пришпандорить Predicate<T>. Правда — это не полностью аналогичное решение. Фильтры с языком все таки более независимы от хранимых данных в коллекции. Ну и насколько я помню (сам уже давно с такими структурами не работал), там есть некоторый аналог индексирования.
С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[7]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, _FRED_, Вы писали:
_FR>Да, для обмена лучше использовать одно представление, для показа — другое, а для рассчётов — третье Остаётся их только подружить и не запутаться во взаимоотношениях.
Интересно сделано в WeFly247(демонстрационное приложение к Whidbey Beta 2), там не стали делать один typedDataSet со связями, а просто нагенерили датасетов по принципу один typedDataSet представляет одну Business Entity.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Улыбаемся и машем :-)
Re[8]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, IT, Вы писали:
GZ>>Решить эти проблемы легко. Их и за проблемы то считать не стоит, неделя работы для простейших случаев. Проблема — DataView. Повторить его функциональность уже значительно сложней.
IT>Думаю что для этого даже недели не понадобится. Особенно на 2-м фреймворке. На работе у меня его нет, приеду домой попробую изобразить кое что.
10 минут на тощак.
ObjectView:
public delegate bool TestObject<T>(T obj);
public class ObjectView
{
public static List<T> Filter<T>(List<T> list, TestObject<T> test)
{
List<T> result = new List<T>();
foreach (T t in list)
if (test(t))
result.Add(t);
return result;
}
public static List<T> Filter<T>(List<T> list, TestObject<T> test, Comparison<T> cmp)
{
List<T> result = new List<T>();
foreach (T t in list)
if (test(t))
result.Add(t);
result.Sort(cmp);
return result;
}
}
Пример использования:
public class Class1
{
public class TestObject
{
public int A;
public int B;
}
public void Exampe(List<TestObject> list)
{
List<TestObject> view = ObjectView.Filter(
list,
delegate(TestObject t)
{
return t.A < t.B;
});
List<TestObject> sortedView = ObjectView.Filter(
list,
delegate(TestObject t)
{
return t.A < t.B;
},
delegate(TestObject x, TestObject y)
{
return x.A - y.A;
});
}
}
И что самое интересное — всё type safety.
Если нам не помогут, то мы тоже никого не пощадим.
Re[9]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, IT, Вы писали:
GZ>>>Решить эти проблемы легко. Их и за проблемы то считать не стоит, неделя работы для простейших случаев. Проблема — DataView. Повторить его функциональность уже значительно сложней.
IT>>Думаю что для этого даже недели не понадобится. Особенно на 2-м фреймворке. На работе у меня его нет, приеду домой попробую изобразить кое что.
IT>10 минут на тощак.
Двойки под рукой нет, поэтому может быть что-то неправильно.
Но тут есть еще вопрос, который меня волнует. Условие фильтрации часто (у меня например) определяется динамически. И в этом случае — язык значительно удобней.
С уважением, Gleb.
... << RSDN@Home 1.1.4 beta 4 rev. 358>>
Re[8]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, G2, Вы писали:
_FR>>Да, для обмена лучше использовать одно представление, для показа — другое, а для рассчётов — третье Остаётся их только подружить и не запутаться во взаимоотношениях.
G2>Интересно сделано в WeFly247(демонстрационное приложение к Whidbey Beta 2), там не стали делать один typedDataSet со связями, а просто нагенерили датасетов по принципу один typedDataSet представляет одну Business Entity.
Дождусь дисков, посмотрю...
<< RSDN@Home 1.1.4 beta 7 rev. 499 >> =11:52= [Windows XP — 5.1.2600.0] {Build at .NET 1.1.4322.2032}
under «*none*»
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Buisness Entities в Распределенных приложениях(наши д
Здравствуйте, GlebZ, Вы писали:
GZ>10 секунд сходу
Можно и так. А ты говоришь неделю
GZ>Но тут есть еще вопрос, который меня волнует. Условие фильтрации часто (у меня например) определяется динамически. И в этом случае — язык значительно удобней.
А ты попробуй сравни. Напиши два варианта и посмотри. Но в любом случае, твой аргумент про отсутствие функциональности как в DataView вычёркиваем.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[11]: Buisness Entities в Распределенных приложениях(наши
Здравствуйте, IT, Вы писали:
GZ>>10 секунд сходу
IT>Можно и так. А ты говоришь неделю
Ну я не подразумевал 2.0. До ноября еще дожить нужно. И еще чтобы при этом деньги были для Microsoft.
GZ>>Но тут есть еще вопрос, который меня волнует. Условие фильтрации часто (у меня например) определяется динамически. И в этом случае — язык значительно удобней. IT>А ты попробуй сравни. Напиши два варианта и посмотри. Но в любом случае, твой аргумент про отсутствие функциональности как в DataView вычёркиваем.
Ок. Частая задача. Пользователю выводится грид. У пользователя есть некоторый набор контролов управления с помощью которого он может его фильтровать и сортировать. В результате, поскольку у нас Predicate<T> привязан к типу, то придется делать для каждого типа объекта свой фильтр. Для DataView все обойдет сбором строки фильтрации.