Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Жутко тормозит Fluent NHibernate / 16 сообщений из 16, страница 1 из 1
01.11.2010, 13:39
    #36931009
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
Добрый день!
Согласно профайлеру FluentConfiguration.BuildConfiguration выполняется 24 секунды. Код, конфигурирующий mapping и connection к БД:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
            MsSqlConfiguration persistenceConfigurer = MsSqlConfiguration
                         .MsSql2005
                         .ConnectionString(connectionStringBuilder => connectionStringBuilder
                                                                        .Server(server)
                                                                        .Database(database)
                                                                        .Username(userName)
                                                                        .Password(password))
                         .ProxyFactoryFactory<ProxyFactoryFactory>()
                         .CurrentSessionContext<ThreadStaticSessionContext>()
                         .DoNot.ShowSql();

            FluentConfiguration cfg = Fluently.Configure()
                    .Database(persistenceConfigurer)
                    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<ExecutorMap>());

            return cfg.BuildConfiguration();
. Количество map-файлов - 19.
Такая длительность построение конфигураций - это нормально??? Возможно ли, что построение конфигурации происходит так долго из-за того, что я где-нибудь криво задал маппинг? На что стоит обратить внимание, для увеличение произовдительности?
...
Рейтинг: 0 / 0
01.11.2010, 14:20
    #36931159
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
Что-то мне подсказывает, что тормозит не только FluentNhibernate, а еще сам NHibernate в процессе создания SessionFactory. Разбор хмl и последующая генерация проксей - дорогое удовольствие.
...
Рейтинг: 0 / 0
01.11.2010, 14:35
    #36931238
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
SolYUtor,

Последующие тормоза тоже наблюдаются, но в данный момент меня больше волнует FluentConfiguration.BuildConfiguration. И главный вопрос: такое время - это мой косяк, или типичное поведение данного инструмента? Насколько я понимаю NHibernate (и Fluent NHibernate) пользуются очень многие во всевозможных проектах, видимо есть какой-то магический способ заставить это работать с приемлемой скоростью. Вот я и пытаюсь понять как.
...
Рейтинг: 0 / 0
01.11.2010, 16:54
    #36931753
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
Почитал исходники Fluent'а. Как и предполагалось, он сначала долго и мучительно генерирует xml, чтобы потом их прочитал NHibernate. А это всё не быстрые операции с текстом + рефлексия. Это Меееедленно, из принципа.
В общем, пишите xml вместо флюент-маппингов, и будет вам быстрее. Или смиритесь со своим временем. Волшебной кнопки "Сделать всё быстро" нет.
...
Рейтинг: 0 / 0
01.11.2010, 17:24
    #36931868
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
SolYUtor,

Как-то все печально получается. Насколько я понимаю FluentNHibernate вначале генерирует все xml-ники, а NHibernate строит маппинги тоже все разом. Нельзя ли как-нибудь этим товарищам сказать, что нужно не все сразу, а по мере необходимости? Глядишь и быстрее будет...
...
Рейтинг: 0 / 0
01.11.2010, 18:05
    #36932011
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
stuffhappens
Нельзя ли как-нибудь этим товарищам сказать, что нужно не все сразу, а по мере необходимости?
Можно. Тут разработчики NHibernate, тут разработчики FluentNhibernate.
Напишите им свои соображения по этому поводу.

stuffhappensГлядишь и быстрее будет...

Сомневаюсь.
...
Рейтинг: 0 / 0
02.11.2010, 09:29
    #36932770
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
Раскинув мозгами на свежую голову, кое-что предпринять можно.
Курим тут , и тут .
...
Рейтинг: 0 / 0
02.11.2010, 11:40
    #36933207
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
SolYUtor,

Огромное спасибо. Буду разбираться. А Вы сами пользуетесь ORM? Какой?
...
Рейтинг: 0 / 0
02.11.2010, 12:49
    #36933441
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
stuffhappens,

NHibernate пользую, и пока весьма им доволен. Правда, маппинги пишу вручную xml'ем.
...
Рейтинг: 0 / 0
02.11.2010, 12:53
    #36933450
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
SolYUtorПравда, маппинги пишу вручную xml'ем.
+1
надёжнее и красивее
...
Рейтинг: 0 / 0
02.11.2010, 14:00
    #36933658
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
SolYUtor,

А как относитесь ко всяким LINQ-провайдорам? Или Cirteria/HQL надежнее и красивее?
...
Рейтинг: 0 / 0
02.11.2010, 14:28
    #36933782
МСУ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
stuffhappensА как относитесь ко всяким LINQ-провайдорам?
Сырые и маломощные. В топку.

stuffhappensИли Cirteria/HQL надежнее и красивее?
Истину глаголите.
...
Рейтинг: 0 / 0
02.11.2010, 16:41
    #36934341
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
stuffhappens,

Если имеется ввиду LINQ to NHibernate - то ничего против имею. Даже некоторые плюсы будут, вроде Intellisense от студии. Но сам не использую, поэтому о степени сырости ничего сказать не могу. В общем, попробуйте - потом сами для себя решите.
ICreateria не люблю - сложно воспринимать. На мой вкус HQL наиболее читабелен.

PS. FluentNHibernate использую для сохраняемости.
...
Рейтинг: 0 / 0
03.11.2010, 14:22
    #36936351
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
Пользуясь случаем, задам вопрос по NHibernate.

Есть 2 таблички: tSources(ID, Name) и tComments(ID, SourceID, Comment, Date) (Связь один-ко-многим).
Требуется по каждому источнику вевести его название и последний (по дате) к нему комменарий.
Классы, описывающие сущности:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
    public class Source
    {
        public virtual int ID { get; set; }
        public virtual string Name { get; set; }

        public virtual IList<Comment> Comments { get; private set; }

        public virtual string LastComment
        {
            get
            {
                if (!Comments.Any())
                    return null;

                return Comments.OrderByDescending(x => x.Date).First().Comment;
            }
        }


        public Source()
        {
            Comments = new List<Comment>();
        }
    }

    public class Comment
    {
        public virtual int ID { get; set; }
        public virtual DateTime Date { get; set; }
        public virtual string Comment { get; set; }
        public virtual Source Source { get; set; }

    }


Классы, задающие маппинг на FluentNH:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
    public class SourceMap : ClassMap<Source>
    {
        public SourceMap()
        {
            Table("dbo.tSource");

            Id(x => x.ID);
            Map(x => x.Name).Column("SourceName");
            HasMany(x => x.Comments).Inverse().Cascade.All();
        }
    }

    public class CommentMap : ClassMap<Comment>
    {
        public CommentMap()
        {
            Id(x => x.ID);
            Map(x => x.Date);
            Map(x => x.Comment);
            References(x => x.Source).Column("SourceID");
        }
    }

.

Ну и для получения нужного результата я получаю все источники и для каждого из них вызываю LastComment. В итого время работы нереально велико. Если посмотреть на SQL-запросы, генерируемые NHibernate, то видно, что для каждого ID источника выполняется запрос типа
Код: plaintext
1.
2.
SELECT * FROM tComments
WHERE SourceID = @p;
@p = n. 
То есть таких запросов выполняется очень много (столько, сколько источников). Почему NHibernate не хочет сделать 1 запрос типа:
Код: plaintext
1.
2.
SELECT s.*, c.* FROM
tSources s LEFT JOIN tComments c
ON s.ID = c.SourceID
?
Может быть его можно заставить это сделать? Как?
Заранее спасибо!
...
Рейтинг: 0 / 0
03.11.2010, 16:12
    #36936724
SolYUtor
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
1. В маппинге Source схему для таблицы указывайте методом Schema, а не Table
2. Классы у вас слишком много позволяют делать со своим состоянием извне. Жестчё инкапсулировать надо.
3. В NHibernate именно вы управляете стратегией извлечения данных. По умолчанию всё грузиться в ленивом режиме, поэтому и получаются такие запросы. Заставить грузить через Left join просто:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    public class SourceMap : ClassMap<Source>
    {
        public SourceMap()
        {
            Table("Source");
            

            Id(x => x.ID);
            Map(x => x.Name).Column("SourceName");
            HasMany(x => x.Comments).Inverse().Cascade.All().Fetch.Join(); //Fetch.Join()!!
        }
    }
Дополнительно можно поиграться с параметром BatchSize

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

Я бы сделал так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
    public class Source
    {
        public virtual int ID { get; set; }
        public virtual string Name { get; set; }

        private IList<Comment> _comments;
        public virtual IList<Comment> Comments
        {
            get { return new List<Comment>(_comments).AsReadOnly(); }
            private set { _comments = value; }
        }

        public virtual Comment LastComment {get; private set;}

        public Source()
        {
            Comments = new List<Comment>();
        }

        public virtual void AddComment(Comment comment)
        {
            LastComment = comment;
            comment.Source = this;
            _comments.Add(comment);
        }
    }

    public class Comment
    {
        public virtual int ID { get; set; }
        public virtual DateTime Date { get; set; }
        public virtual string Comments { get; set; }
        public virtual Source Source { get; set; }

    }

    public class SourceMap : ClassMap<Source>
    {
        public SourceMap()
        {
            Table("Source");
            

            Id(x => x.ID);
            Map(x => x.Name).Column("SourceName");
            HasMany(x => x.Comments).Access.CamelCaseField(Prefix.Underscore).Inverse().Cascade.All();
            References(source => source.LastComment).Fetch.Join();
        }
    }

    public class CommentMap : ClassMap<Comment>
    {
        public CommentMap()
        {
            Id(x => x.ID);
            Map(x => x.Date);
            Map(x => x.Comments);
            References(x => x.Source).Column("SourceID");
        }
    }

    [TestFixture]
    public class EagerFetchingFixture
    {
        #region Setup/Teardown

        [SetUp]
        public void SetUp()
        {

            var persister = SQLiteConfiguration
                .Standard
                .UsingFile("Test.db")
                .ShowSql();


             _config = Fluently
                 .Configure()
                 .Database(persister)
                 .Mappings(map => map.FluentMappings.AddFromAssemblyOf<Source>())
                .BuildConfiguration();

             _sessionFactory = _config.BuildSessionFactory();

             new SchemaExport(_config).Execute(true, true, false);
        }

        #endregion

        private ISessionFactory _sessionFactory;
        private Configuration _config;

        [Test]
        public void Test()
        {
            using(var session = _sessionFactory.OpenSession())
            {
                var source = new Source {Name = Guid.NewGuid().ToString()};

                source.AddComment(new Comment {Comments = Guid.NewGuid().ToString(), Date = DateTime.Now});
                source.AddComment(new Comment { Comments = Guid.NewGuid().ToString(), Date = DateTime.Now});
                source.AddComment(new Comment { Comments = Guid.NewGuid().ToString(), Date = DateTime.Now});

                session.Persist(source);
                session.Flush();
                session.Clear();

                var s2 = session.Get<Source>(1);

                var comment = s2.LastComment.Comments;
                
            }
        }

Результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
drop table if exists "Comment"

    drop table if exists Source

    create table "Comment" (
        ID  integer,
       Date DATETIME,
       Comments TEXT,
       SourceID INTEGER,
       primary key (ID)
    )

    create table Source (
        ID  integer,
       SourceName TEXT,
       LastComment_id INTEGER,
       primary key (ID)
    )
NHibernate: INSERT INTO Source (SourceName, LastComment_id) VALUES (@p0, @p1); select last_insert_rowid();@p0 = 'cfe8d711-876c-4bca-96f1-f2f410d8fdea', @p1 = NULL
NHibernate: INSERT INTO "Comment" (Date, Comments, SourceID) VALUES (@p0, @p1, @p2); select last_insert_rowid();@p0 = 03.11.2010 16:07:20, @p1 = '44c7b1fc-8bae-4cb3-a4ac-5dcdbb02884a', @p2 = 1
NHibernate: INSERT INTO "Comment" (Date, Comments, SourceID) VALUES (@p0, @p1, @p2); select last_insert_rowid();@p0 = 03.11.2010 16:07:20, @p1 = '01156992-8cab-4100-8311-0e9e29e9c659', @p2 = 1
NHibernate: INSERT INTO "Comment" (Date, Comments, SourceID) VALUES (@p0, @p1, @p2); select last_insert_rowid();@p0 = 03.11.2010 16:07:20, @p1 = 'af72a15a-0aa5-4ca5-ab97-40b8e0e53d86', @p2 = 1
NHibernate: UPDATE Source SET SourceName = @p0, LastComment_id = @p1 WHERE ID = @p2;@p0 = 'cfe8d711-876c-4bca-96f1-f2f410d8fdea', @p1 = 3, @p2 = 1
NHibernate: SELECT source0_.ID as ID1_1_, source0_.SourceName as SourceName1_1_, source0_.LastComment_id as LastComm3_1_1_, comment1_.ID as ID0_0_, comment1_.Date as Date0_0_, comment1_.Comments as Comments0_0_, comment1_.SourceID as SourceID0_0_ FROM Source source0_ left outer join "Comment" comment1_ on source0_.LastComment_id=comment1_.ID WHERE source0_.ID=@p0;@p0 = 1


5. Рекомендую осилить NHibernate in Action.
...
Рейтинг: 0 / 0
08.11.2010, 11:18
    #36941685
stuffhappens
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Жутко тормозит Fluent NHibernate
SolYUtor,

Спсибо за ответ!
Изучал NHibernate по вот этим скринкастам , но качеством материала остался недоволен. Видимо, действительно нужно читать NHibernate in action.
...
Рейтинг: 0 / 0
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Жутко тормозит Fluent NHibernate / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]