Решение для вложенных объектов
От: b0bi  
Дата: 14.03.07 11:33
Оценка: 18 (1)
Доброго времени суток, уважаемые.

Хочу предложить на суд свою реализацию для работы с вложенными объектами на BLT.
http://rsdn.ru/File/58558/Person_on_BLT.rar
На форуме много споров, но конкретного законченного решения я не нашел.
Решение основано на справочниках, которые загружаются по мере необходимости и по истечению заданного таймаута выгружаются из памяти. В общем смотрите.....

Так же предлагаю совместными усилиями улучшить это решение.
Сразу скажу, что в BLT я новичок, так что не судите строго. Хочется совместно разобраться как лучше реализовать основу, для дальнейшей своей работы, а так же помочь ищущим найти решение.
Пишите, пожалуйста, свои пожелания, предложиния и замечания сюда, будем обсуждать.
Re: Решение для вложенных объектов
От: b0bi  
Дата: 14.03.07 13:50
Оценка:
B>http://rsdn.ru/File/58558/Person_on_BLT.rar

Person_on_BLT\SCRIPT\create.sql Изменено 14.03.07 16:48
Person_on_BLT\Person_on_BLT\ObjectModel\Person.cs Изменено 14.03.07 16:48
Re: Решение для вложенных объектов
От: IT Россия linq2db.com
Дата: 15.03.07 00:01
Оценка:
Здравствуйте, b0bi, Вы писали:

B>Хочу предложить на суд свою реализацию для работы с вложенными объектами на BLT.


Какую проблему решает данное решение?
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Сказано же: "вложенных объектов"
От: Блудов Павел Россия  
Дата: 15.03.07 03:13
Оценка:
Здравствуйте, IT, Вы писали:

IT>Какую проблему решает данное решение?

Проблему размножения сушьностей.
Person p1 = SomeAccessor.SelectByKey(1);
Person p2 = SomeAccessor.SelectByKey(1);
Assert.ReferenceEquals(p1, p2);


Смысл в том, что если один и тот же объект поднимается с базы несколько раз, то вместо копии нужно вернуть оригинал.
Если это достижимо, то все танцы вокруг master-slaves ака order-details решаются сами собой.

Но тут есть куча проблем: например, как решить, что этот один и тот же объект или всё-таки разные? Как узнать, что объект уже никому не нужен и его можно выкинуть из кеша? Как одновременно свести к минимуму использование памяти и не потерять при этом в скорости? И ещё куча

В принципе, всё это так или иначе решается. Правда исключительно путём добавления разного рода ограничений.
В частности, в этом Решении жизнено необходимо, чтобы у каждого объекта в базе был неизменяемый primary key типа Int32.
Кроме того, объектов в базе должно быть очень мало, т.к. все таблицы целиком считываются из базы и кешируются в памяти слоя бизнес логики.

Зато можно делать так:
    public abstract class Person
    {
        [NullValue(0)]
        public abstract int CityID { get; set; }
        [MapIgnore]
        public City City {
            get { return (City)DictionaryManager.GetInstance()[typeof(City)][CityID]; }
            set { CityID = value.ID; } 
        }
    }


Бредовая идея


В принципе, можно заложить в BLToolkit основу для master-slave логики. Т.е. написать некий RelationAttribute, и добавить в DataAcessorBase пару методов, кидающих NotSupportedException. Тогда конечные пользователи смогит прикрутить к этой системе какие им угодно потроха.
    public abstract class Person : SomeBase
    {
        [Relation("CityID")] // Полный список полей составляющих PK
        public abstract City City
        { 
            get; // Идём туда, не знаю куда с PK и получаем объект или null.
            set; // Получаем объект или null и мапим его PK на заданные поля.
        }
    }

Но тут есть одна проблема: каждый объект типа Person (или SomeBase) должен быть связан с каким либо DataAccessor'ом. Хочется сделать всё просто, но в то же время гибко.
... << RSDN@Home 1.2.0 alpha rev. 642>>
Re: Решение для вложенных объектов
От: Блудов Павел Россия  
Дата: 15.03.07 05:50
Оценка:
Здравствуйте, b0bi, Вы писали:

B>Решение основано на справочниках, которые загружаются по мере необходимости и по истечению заданного таймаута выгружаются из памяти. В общем смотрите.....

Хм... Знаете, как называется первый по алфавиту файл в исходниках BLToolkit?

Aspects\CacheAspect.cs

Соответственно, первый unit-test называется

Aspects\CacheAspectTest.cs


Этот аспект занимается кешированием результатов вызова методов. Например:
public abstract class SomeAccessor : DataAccessor
{
    [NoInstance]
    public abstract Dictionary<int, City> Cities
    {
        [Cache(36000000)]        // 10 мин
        [SqlQuery("SELECT * FROM Cities")]
        get;
    }
}

[Test]
public void CacheTest()
{
    Dictionary<int, City> dic = _da.Cities;
    Assert.AreEqual("Москва", dic[0].Name);
}


... << RSDN@Home 1.2.0 alpha rev. 642>>
Re[2]: Решение для вложенных объектов
От: b0bi  
Дата: 15.03.07 06:20
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

БП>Этот аспект занимается кешированием результатов вызова методов. Например:


Да, действительно, полезная вещь, жалко я о ней не знал раньше. Надо будет все UnitTest'ы внимательно проштудировать.
Re: Сказано же: "вложенных объектов"
От: b0bi  
Дата: 15.03.07 06:50
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

Согласен что это не панацея, не очень универсально. Этот вариант можно использовать для загрузки объектов из небольших таблиц (простейших справочников, типа "Города"), ну a то, что сложнее — ручками. А ведь по большей части справочники в БД, это как правило не большие таблицы (хотя случаи бывают разные), и такой подход экономит кучу времени.

БП>как решить, что этот один и тот же объект или всё-таки разные?


Конечно справочник должен иметь неизменяемый primary key типа Int32, объект не имеющий PK здесь никак не получится использовать.

БП>Как узнать, что объект уже никому не нужен и его можно выкинуть из кеша?


Таймаут решает эту проблемму.

БП>Как одновременно свести к минимуму использование памяти и не потерять при этом в скорости?


Только не большие справочники........ Действительно, это серьёзное ограничение.

БП>В принципе, всё это так или иначе решается. Правда исключительно путём добавления разного рода ограничений.

БП>В частности, в этом Решении жизнено необходимо, чтобы у каждого объекта в базе был неизменяемый primary key типа Int32.
БП>Кроме того, объектов в базе должно быть очень мало, т.к. все таблицы целиком считываются из базы и кешируются в памяти слоя бизнес логики.

Собственно, вы же на всё это и ответили. Со всем согласен. ...... остальное ручками......


БП>

Бредовая идея


...

БП>Но тут есть одна проблема: каждый объект типа Person (или SomeBase) должен быть связан с каким либо DataAccessor'ом. Хочется сделать всё просто, но в то же время гибко.


Было бы неплохо, действительно облегчило бы жизнь. Сейчас ведь приходится делать тоже более сложными способами.
Re: Сказано же: "вложенных объектов"
От: b0bi  
Дата: 15.03.07 06:53
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

Согласен что это не панацея, не очень универсально. Этот вариант можно использовать для загрузки объектов из небольших таблиц (простейших справочников, типа "Города"), ну a то, что сложнее — ручками. А ведь по большей части справочники в БД, это как правило не большие таблицы (хотя случаи бывают разные), и такой подход экономит кучу времени.

БП>как решить, что этот один и тот же объект или всё-таки разные?


Конечно справочник должен иметь неизменяемый primary key типа Int32, объект не имеющий PK здесь никак не получится использовать.

БП>Как узнать, что объект уже никому не нужен и его можно выкинуть из кеша?


Таймаут решает эту проблемму.

БП>Как одновременно свести к минимуму использование памяти и не потерять при этом в скорости?


Только не большие справочники........ Действительно, это серьёзное ограничение.

БП>В принципе, всё это так или иначе решается. Правда исключительно путём добавления разного рода ограничений.

БП>В частности, в этом Решении жизнено необходимо, чтобы у каждого объекта в базе был неизменяемый primary key типа Int32.
БП>Кроме того, объектов в базе должно быть очень мало, т.к. все таблицы целиком считываются из базы и кешируются в памяти слоя бизнес логики.

Собственно, вы же на всё это и ответили. Со всем согласен. ...... остальное ручками......


БП>Бредовая идея


...

БП>Но тут есть одна проблема: каждый объект типа Person (или SomeBase) должен быть связан с каким либо DataAccessor'ом. Хочется сделать всё просто, но в то же время гибко.


Было бы неплохо, действительно облегчило бы жизнь. Сейчас ведь приходится делать тоже самое более сложными способами.
Re[2]: Решение для вложенных объектов
От: b0bi  
Дата: 15.03.07 13:37
Оценка:
Изменения

B>>http://rsdn.ru/File/58558/Person_on_BLT.rar


Person_on_BLT\Person_on_BLT\BusinessLogic\DictionaryManager.cs изменено 15.03.07 13:24
Person_on_BLT\Person_on_BLT\ObjectModel\Person.cs изменено 15.03.07 16:28
Person_on_BLT\Person_on_BLT\UnitTest\DictionaryesTest.cs изменено 15.03.07 13:24

Используется атрибут Cache из BLT\Aspects\CacheAspect.cs, обсуждалось http://rsdn.ru/Forum/Message.aspx?mid=2405480&amp;only=1
Автор: Блудов Павел
Дата: 15.03.07
Re: Сказано же: "вложенных объектов"
От: IT Россия linq2db.com
Дата: 15.03.07 14:18
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

Хочется сделать всё просто, но в то же время гибко.

Хранилище объектов?

Проблема в том, что решение этой задачи связано с введением множества ограничений и неоптимальностей. Если есть желание обсудить эту задачу, то начинать нужно именно с их обсуждения.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Сказано же: "вложенных объектов"
От: b0bi  
Дата: 15.03.07 14:56
Оценка:
Здравствуйте, IT, Вы писали:


IT>Проблема в том, что решение этой задачи связано с введением множества ограничений и неоптимальностей. Если есть желание обсудить эту задачу, то начинать нужно именно с их обсуждения.


На ваш взгляд, какие недостатки у предложенного решения, кроме сказанного выше.

Предлагаю начать обсуждение с проблеммы "Как одновременно свести к минимуму использование памяти и не потерять при этом в скорости?"
Как вариант, можно загружать не целиком объекты, а только те поля, которые считаешь нужным....... А ещё можно записи подгружать по одной, по мере необходимости, но в этом случае произодительность страдает.

>БП Хочется сделать всё просто, но в то же время гибко.

А что если не кидать NotSupportedException, когда пользователь не прикрутил DataAccessor'у потроха, а самим пытаться достать данные, ведь всё для этого есть.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.