Nhibernate:在事务中插入新的子数据并持久化父数据
我有两个班,作为父母的旅行和作为孩子的机票Nhibernate:在事务中插入新的子数据并持久化父数据,nhibernate,transactions,version,Nhibernate,Transactions,Version,我有两个班,作为父母的旅行和作为孩子的机票 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; } } 在事务中,如何确保在
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,并且在其他事务中未被修改。如果我检查trip的一个版本,它仍然可以在其他事务上修改。如果我(在所选的行程中)锁定,它将有一个性能问题,因为在一秒钟内有数千个票插入。
谢谢您的建议。//将课堂改为
// 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);
}
公务舱旅行:实体
{
公共int版本{get;private set;}
公共字符串TripNo{get;set;}
公共字符串是活动的{get;set;}
}
//使用FluentNhibernate映射进行配置
//在TripMap中
版本(t=>t.Version);
//像这样使用
void AddTicket(字符串tripno、字符串ticketNo)
{
布尔中断=假;
做
{
中断=错误;
尝试
{
使用(var tx=session.BeginTransaction())
{
var trip=session.Query();
如果(行程==null)
返回;
var票证=新票证{TicketNo=TicketNo,Trip=Trip};
会话。保存或更新(票据);
tx.Commit()
}
}
捕获(StaleObjectException)
{
//有人把旅行搞砸了
中断=真;
}
}当(被打断);
}
更新:为了证明它,请加载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
}
var config=fluntly.Configure()
.Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
.Mappings(m=>m.FluentMappings
.Add()
)
.BuildConfiguration();
var sf=config.BuildSessionFactory();
使用(var session=sf.OpenSession())
使用(var session2=sf.OpenSession(session.Connection))//使用相同的连接,因为内存中的数据库绑定到该连接,但是会话的行为就像它们有不同的连接一样
{
新SchemaExport(config.Execute)(true、true、false、session.Connection、null);
//填充数据库
int tripId=session.Save(新Trip{No=“1”});
session.Flush();
session.Clear();//清除缓存
var user1=session.Get(tripId);
var user2=session2.Get(tripId);
user1.No=2;
user2.No=3;
session.Flush();
session2.Flush();//此处抛出StaleObjectException
}
旅行和机票之间的关系是一对多、多对多还是一对一?嗯,我忘了怎么改变旅行了。否则,NHibernate不会对其进行更改。我将在明天回顾您的解决方案,该解决方案显示,如果在事务中间修改trip,NHibernate将抛出StaleObjectException。如何证明呢?