Nhibernate: вставка новых дочерних данных и сохранение родителя в транзакции - PullRequest
0 голосов
/ 05 марта 2012

У меня два класса, Trip как родитель и Ticket как ребенок

public class Trip : Entity
{
   public string TripNo { get; set; }
   public string IsActive { get; set; }
}

public class Ticket : Entity
{
   public Trip Trip { get; set; }
   public string TicketNo { get; set; }
}

В транзакции, как мне убедиться, что новый билет добавлен вместе с Trip.IsActive, имеет значение true и не изменяется в другой транзакции. Если я проверю версию поездки, она все еще может быть изменена для другой транзакции. Если я сделал блокировку (в выбранной Поездке), у нее будет проблема с производительностью, поскольку в секунду вставляются тысячи билетов. Спасибо за все советы.

1 Ответ

1 голос
/ 05 марта 2012
// change class to 
public class Trip : Entity
{
   public int Version { get; private set; }

   public string TripNo { get; set; }
   public string IsActive { get; set; }
}

// configure using FluentNhibernate Mapping
// in TripMap
Version(t => t.Version);

// use like this
void AddTicket(string tripno, string ticketNo)
{
    bool interupted = false;
    do
    {
        interupted = false;
        try
        {
            using(var tx = session.BeginTransaction())
            {
                var trip = session.Query<Trip>().Where(t => t.TripNo == tripno && t.IsActive).FirstOrDefault();
                if (trip == null)
                    return;
                var ticket = new Ticket { TicketNo = ticketNo, Trip = trip };
                session.SaveOrUpdate(ticket);
                tx.Commit()
            }
        }
        catch(StaleObjectException)
        {
            // someone messed up with the Trip
            interupted = true;
        }
    } while (interupted);
}

Обновление: чтобы доказать это, загрузите System.Data.Sqlite.dll и создайте новое ConsoleApp со следующим кодом

var config = Fluently.Configure()
    .Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
    .Mappings(m => m.FluentMappings
        .Add<TripMap>()
    )
    .BuildConfiguration();

var sf = config.BuildSessionFactory();

using (var session = sf.OpenSession())
using (var session2 = sf.OpenSession(session.Connection))  // use the same connection because inmemory dbs are bound to the connection, nevertheless the session act as if they have different connections
{
    new SchemaExport(config).Execute(true, true, false, session.Connection, null);

    // fill the database
    int tripId = session.Save(new Trip { No = "1" });
    session.Flush();
    session.Clear();  // Clear cache

    var user1 = session.Get<Trip>(tripId);
    var user2 = session2.Get<Trip>(tripId);

    user1.No = 2;
    user2.No = 3;

    session.Flush();
    session2.Flush(); // throws StaleObjectException here
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...