Как обеспечить хорошую производительность с MassTransit Saga, которая добавляет элемент в IList, сохраняемый в NHibernate

У меня есть сага, в которой есть 3 состояния -

    public static State Initial { get; set; }
    public static State ReceivingRows { get; set; }
    public static State Completed { get; set; }

Он переходит от Initial к ReceiveRows, когда получает BofMessage (где Bof = начало файла). После BofMessage он получает большое количество сообщений RowMessage, каждое из которых описывает строку в плоском файле. После отправки всех RowMessages отправляется EofMessage, и состояние изменяется на Completed. Наблюдать -

static void DefineSagaBehavior()
{
    Initially(When(ReceivedBof)
        .Then((saga, message) => saga.BeginFile(message))
        .TransitionTo(ReceivingRows));

    During(ReceivingRows, When(ReceivedRow)
        .Then((saga, message) => saga.AddRow(message)));

    During(ReceivingRows, When(ReceivedRowError)
        .Then((saga, message) => saga.RowError(message)));

    During(ReceivingRows, When(ReceivedEof)
        .Then((saga, message) => saga.EndFile(message))
        .TransitionTo(Completed));
}

public override void OnAddRow(ParcelRowMessage message)
{
    // ensure isCauvReturned is "Y"
    var fields = message.Value;
    var isCauvReturned = fields[33] == "Y";
    if (!isCauvReturned)
        return;

    // add row with just parcel number
    var parcelNumber = fields[1];
    var row = parcelNumber;
    _rows.Add(row);
}

Это работает, за исключением того, что у него производительность n-squared. Исследование с помощью NHProf показывает, что каждая добавленная строка приводит к тому, что весь список строк выглядит следующим образом:

А) выбрано из базы данных

Б) удалить из базы данных

в) повторно внесены в базу данных.

Мне это кажется очень плохим поведением. Все, что нужно для добавления строки, это… ну, добавить одну строку в базу данных! Операция добавления — буквально единственное, что я делаю со списком строк. Это не масштабируется, когда у нас есть 10 000 элементов в списке.

Кто-нибудь знает, как придать этой саге более вменяемое поведение производительности?

Кстати - вот как отображается IList, если вам это нужно -

        HasMany(x => x.Rows)
            .Table("OwnerHistorySagaRow")
            .KeyColumn("CorrelationId")
            .Element("Row")
            .Cascade.AllDeleteOrphan();

Спасибо!


person Bryan Edds    schedule 22.05.2012    source источник


Ответы (2)


Я знаю, что это мертвый предмет, но вот реальный ответ, как заставить сумку работать должным образом.

Bag(x => x.Rows, c =>
{
    c.Key(k =>
    {
        k.Column("RowCorrelationId");
        k.ForeignKey("FK_State_Row");
        k.NotNullable(true);
    });
    c.Fetch(CollectionFetchMode.Join);
    c.Lazy(CollectionLazy.NoLazy);
    c.Cascade(Cascade.All);
}, r => r.OneToMany());

Тип класса для RowsIList<Row>.

person Chris Patterson    schedule 25.02.2015